ok Thanks! Sure I can write that, where do you need the result of it? Sebastian
2012/10/26 Maxim Solodovnik <[email protected]> > OK > no problem > lets remove it > > can you please write RPC call performing user count retrieving? > > > On Fri, Oct 26, 2012 at 2:55 PM, [email protected] < > [email protected]> wrote: > >> I agree however that are more comfortable way of getting RoomClients by >> RoomId might be needed. >> However this is a very different issue. >> This is no argument for moving it to the database. >> You can organize the data structure in the memory more efficiently, make >> several Lists for fast access et cetera. >> Or for example store it using EHCache. I thought also that it was our >> plan that at some point we will externalize the session vars to EHCache, so >> that you have the chance to configure the session storage size and >> externalize it to disk in case needed. >> >> Sebastian >> >> 2012/10/26 [email protected] <[email protected]> >> >> the standard call to get a room client is not to get the roomclients by >>> its roomid. >>> The standard call to get a room client is to get the roomclient by its >>> streamid !!! >>> And this call is done for every RoomClient per sync method. >>> So if there are 100 clients in a room = 100 db calls per sync. >>> I thought I have tried to explain the calculation. >>> >>> I just don't understand this whole discussion, we have a single >>> requirement: >>> Calculate the list of users per room. >>> And now we need to switch a session object to the database? >>> >>> I don't see a need for a hybrid solution to have session objects twice. >>> There will be multiple issues in syncing the information in the session >>> objects: >>> A single user can create 2 or 3 RTMP connection to the server. >>> It will not be get simpler by your solution: >>> If the users connects as "Screensharing Client" your logic will not >>> detect it. >>> If the user connects as "Audio/Video Client" your logic will not detect >>> it. >>> So actually you will have multiple methods in the >>> ScopeApplicationAdapter where you will have to sync the session object to >>> the database otherwise the database object is of quite limited use. >>> >>> I really don't think splitting up that logic to database and session >>> makes things more easy. >>> All you want is to use a query like "SELECT ROOM JOIN FETCH >>> ROOMATTENDEE" ;) >>> Just for having such a query we are not going to switch around a session >>> object to the database. >>> It just has too many drawbacks. >>> >>> >>> Sebastian >>> >>> 2012/10/26 Maxim Solodovnik <[email protected]> >>> >>>> I'm afraid I never can get why do we need to perform RPC call (no >>>> matter by client or by server) if we already have common DB and can use it. >>>> >>>> DB can be used even if RoomClient is not DB Entity. >>>> >>>> I still think that if code will be changed from >>>> for (Set<IConnection> conset : conCollection) { >>>> for (IConnection conn : conset) { >>>> if (conn != null) { >>>> RoomClient rcl = this.clientListManager >>>> .getClientByStreamId(conn >>>> .getClient().getId()); >>>> if (rcl == null) { >>>> // continue; >>>> } else if (rcl.getIsScreenClient() != null >>>> && rcl.getIsScreenClient()) { >>>> // continue; >>>> } else { >>>> if (!streamid.equals(rcl.getStreamid())) { >>>> // do staff here >>>> } >>>> } >>>> } >>>> } >>>> } >>>> >>>> >>>> to: >>>> for (RoomClient rc : clientListManager.getClientListByRoom(roomId)) { >>>> // do same staff here >>>> } >>>> >>>> we will have >>>> 1) only one DB call per broadcast >>>> 2) 1 loop instead 2 nested loops >>>> 3) no 3 level filtering inside second loop >>>> >>>> >>>> To implement your solution and remove RoomClient from DB, I propose the >>>> following: >>>> 1) remove RoomClient from DB >>>> 2) add RoomAttendee Entity to the DB (it will contain minimal attendee >>>> info and will be queried only to get room clients and their basic info >>>> while getting list of users currently in room) >>>> >>>> Is it OK? >>>> >>>> On Fri, Oct 26, 2012 at 2:11 PM, [email protected] < >>>> [email protected]> wrote: >>>> >>>>> Now userC opens OM installed on serverA >>>>> => userC asks for the list of rooms including the number of users. >>>>> The server side will calc the users per room. Either by calculating >>>>> the rooms locally, or by perrforming a RPC call to the connected server to >>>>> get the list of current usercount per room. >>>>> userC will only peform a single call, server might do mulitple calls >>>>> to calc the usercount, but it sends back a single answer. >>>>> So there is no multiple calls needed. >>>>> For a future iteration we might also think about a master slave >>>>> principle where the slave always automatically pushes current usercount to >>>>> the master, so there is no need for the master to ask for the usercount. >>>>> >>>>> However for the time being I think it is acceptable, with a scenario >>>>> of 2-3 servers in the cluster such a RPC call might take 2 seconds longer >>>>> then currently, but I think that is ok for now. >>>>> >>>>> Sebastian >>>>> >>>>> >>>>> 2012/10/26 Maxim Solodovnik <[email protected]> >>>>> >>>>>> Hello Sebastian, >>>>>> >>>>>> Imagine the following situation: >>>>>> We have 2 servers: serverA and serverB, both have OM installed with >>>>>> same DB >>>>>> We have 2 rooms: roomA (assigned to serverA) and roomB (assigned to >>>>>> serverB) each have 10 active users in it right now >>>>>> >>>>>> Now userC opens OM installed on serverA >>>>>> In the list of rooms he can see roomA (user count can be get by >>>>>> counting connections) and roomB (no user count) >>>>>> >>>>>> performing RTMP call from client to both server seems to be possible >>>>>> but complicated solution for the LZX client, but it seems to >>>>>> me unacceptable for the wicket client. >>>>>> >>>>>> >>>>>> >>>>>> On Wed, Oct 24, 2012 at 5:13 PM, [email protected] < >>>>>> [email protected]> wrote: >>>>>> >>>>>>> How do you handle rooms in general in that solution, is a single >>>>>>> room always on the same server instance. >>>>>>> Or in other words: >>>>>>> Can it happens that two users are in the same room but on different >>>>>>> servers? >>>>>>> Cause from my point of view that is impossible. >>>>>>> You can't stream a video from server instance 1 and from instance 2 >>>>>>> at the same time. >>>>>>> So users of a one room are always on the same server. >>>>>>> That should also make the calculation easier. >>>>>>> >>>>>>> The other point is of course you will have to write a script that >>>>>>> will collect the number of users per room from all server instances and >>>>>>> then calculate the sum of it. >>>>>>> I would collect this on the server side and then give the client >>>>>>> just the result of it. For the client it would look like a single RPC >>>>>>> call, >>>>>>> while on server side, the server asks each instance for its usage >>>>>>> numbers/statistics. >>>>>>> >>>>>>> >>>>>>> Sebastian >>>>>>> >>>>>>> 2012/10/24 Maxim Solodovnik <[email protected]> >>>>>>> >>>>>>>> If there is only 1 server - all your solutions will work. >>>>>>>> But imaging we have 2 servers. Each have its own room full of >>>>>>>> clients. >>>>>>>> >>>>>>>> Now User enters server1 and would like to see how much users in >>>>>>>> each room. >>>>>>>> But it is impossible since server1 only have >>>>>>>> connections/roomClients only for 1 server, and have no information >>>>>>>> regarding second one. >>>>>>>> >>>>>>>> >>>>>>>> On Wed, Oct 24, 2012 at 4:32 PM, [email protected] < >>>>>>>> [email protected]> wrote: >>>>>>>> >>>>>>>>> *I see no other way to get the number of users (per server)* >>>>>>>>> => There are at least three alternative ways to get this number: >>>>>>>>> a) You count the number of connection of a certain scope and then >>>>>>>>> take the sum of it >>>>>>>>> This will give you the total number of connections, no matter if >>>>>>>>> audio/video, conferencing or a screensharing connection. >>>>>>>>> b) You count the total number of RoomClients from the current >>>>>>>>> session >>>>>>>>> This will give you the total number of connections, no matter if >>>>>>>>> audio/video, conferencing or a screensharing connection. >>>>>>>>> c) You count the total number of RoomClients from the current >>>>>>>>> session, but you filter the result based on if the RoomClient is a >>>>>>>>> Audio/Video client or a Screensharing client >>>>>>>>> With this method you would be able to calc the exact number of >>>>>>>>> Audio/Video connection >>>>>>>>> >>>>>>>>> Which of those would fit yours? >>>>>>>>> Or did I misunderstood something? >>>>>>>>> >>>>>>>>> Sebastian >>>>>>>>> >>>>>>>>> >>>>>>>>> 2012/10/24 Maxim Solodovnik <[email protected]> >>>>>>>>> >>>>>>>>>> Hello Sebastian, >>>>>>>>>> >>>>>>>>>> I'm afraid we need something like "lightweight RoomClient" in the >>>>>>>>>> DB to resolve 3) >>>>>>>>>> This can be done without performance degradation. >>>>>>>>>> I see no other way to get the number of users. >>>>>>>>>> >>>>>>>>>> On Wed, Oct 24, 2012 at 3:31 PM, [email protected] < >>>>>>>>>> [email protected]> wrote: >>>>>>>>>> >>>>>>>>>>> So will we find a consens here? :) >>>>>>>>>>> >>>>>>>>>>> 1) No DB query in Sync methods to keep performance up >>>>>>>>>>> 2) Session objects should not stay in a database but in memory >>>>>>>>>>> 3) To have the number of users per server instance there is no >>>>>>>>>>> need to have the RoomClient in the database. >>>>>>>>>>> >>>>>>>>>>> Can we find a consens based on those resolutions? >>>>>>>>>>> >>>>>>>>>>> Sebastian >>>>>>>>>>> >>>>>>>>>>> 2012/10/22 [email protected] <[email protected]> >>>>>>>>>>> >>>>>>>>>>> Practically in this case you would have to iterate thorugh the >>>>>>>>>>>> connection. >>>>>>>>>>>> You could also call IConnection => getConnection => getSize. >>>>>>>>>>>> This would give a rough idea. But as you don't know how many of >>>>>>>>>>>> those connection are screensharing or Audio/Video you can't tell >>>>>>>>>>>> how many >>>>>>>>>>>> users exactly there are. >>>>>>>>>>>> >>>>>>>>>>>> If you want to share this information with others I would >>>>>>>>>>>> suggest you simply add a SOAP/REST call and in that sense query >>>>>>>>>>>> the number >>>>>>>>>>>> of users via a HTTP call. >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> Sebastian >>>>>>>>>>>> >>>>>>>>>>>> 2012/10/22 Maxim Solodovnik <[email protected]> >>>>>>>>>>>> >>>>>>>>>>>>> If I remember correctly I have added RoomClient to the DB >>>>>>>>>>>>> since I need mechanism to retrieve how much users are currently >>>>>>>>>>>>> in the room. >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> On Mon, Oct 22, 2012 at 3:23 PM, [email protected] < >>>>>>>>>>>>> [email protected]> wrote: >>>>>>>>>>>>> >>>>>>>>>>>>>> We could even store it currently in the IConnection. The Red5 >>>>>>>>>>>>>> framework has the similar mechanism like the static Map that >>>>>>>>>>>>>> I've build. >>>>>>>>>>>>>> >>>>>>>>>>>>>> We will also stay with our Red5 implementation for the next 6 >>>>>>>>>>>>>> months as we have no alternative to stream audio/video in HTML5. >>>>>>>>>>>>>> >>>>>>>>>>>>>> It is no option to stay with it, how can we offer >>>>>>>>>>>>>> OpenMeetings to be scalable to 1000 concurrent users? We would >>>>>>>>>>>>>> have to >>>>>>>>>>>>>> limit it to 250. Also it would become mandatory to have the >>>>>>>>>>>>>> database server >>>>>>>>>>>>>> on the same machine as the red5 server. Otherwise you have >>>>>>>>>>>>>> performance >>>>>>>>>>>>>> bottlenecks. Can you imagine what kind of negative public >>>>>>>>>>>>>> feedback we will >>>>>>>>>>>>>> have if every question about performance of red5 is answered >>>>>>>>>>>>>> with: Did you >>>>>>>>>>>>>> install db server on another instance of your network? >>>>>>>>>>>>>> >>>>>>>>>>>>>> Sorry but it is not possible. Also not for a temporary >>>>>>>>>>>>>> solution. We can't sell this product like that and claim to have >>>>>>>>>>>>>> 1000 user >>>>>>>>>>>>>> sessions per server unit. >>>>>>>>>>>>>> >>>>>>>>>>>>>> What requirements do exist to store the RoomClient in the >>>>>>>>>>>>>> database and what is needed to be done to remove it from the db >>>>>>>>>>>>>> again? >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> Sebastian >>>>>>>>>>>>>> >>>>>>>>>>>>>> 2012/10/22 Maxim Solodovnik <[email protected]> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> OK, I'm not insist. I believe RoomClient will be removed in >>>>>>>>>>>>>>> the future. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> On Mon, Oct 22, 2012 at 3:00 PM, [email protected] < >>>>>>>>>>>>>>> [email protected]> wrote: >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Sorry but: >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> for (RoomClient rc: allClient) { >>>>>>>>>>>>>>>> if (rc.getPublicSID().equals(_publicSID) { >>>>>>>>>>>>>>>> return rc; >>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> That is simply not true. >>>>>>>>>>>>>>>> There are _some_ implementations where it was needed that >>>>>>>>>>>>>>>> you need to get the RoomClient by its public SID. However this >>>>>>>>>>>>>>>> usage was >>>>>>>>>>>>>>>> quite limited. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> In general it was the way I described it: >>>>>>>>>>>>>>>> The maps key was the streamid. And the streamid was >>>>>>>>>>>>>>>> obtained from the IConnection of each stream. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/remote/red5/ClientListManager.java?revision=1339514&view=markup >>>>>>>>>>>>>>>> Line 118, that was the function that was mainly in use all >>>>>>>>>>>>>>>> over the application. >>>>>>>>>>>>>>>> There is no sorting, there is no iteration => nothing. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Search in the ScopeApplicationAdapter for >>>>>>>>>>>>>>>> "getClientByStreamId" => 52 of matches. >>>>>>>>>>>>>>>> Every of this call is now replaced by a single DB query. >>>>>>>>>>>>>>>> And if you iterate like described through all connection >>>>>>>>>>>>>>>> (like it is in EVERY snyc method) >>>>>>>>>>>>>>>> You will do a single query for EVERY connection. >>>>>>>>>>>>>>>> Like 100 users in a room => 100 queries. >>>>>>>>>>>>>>>> Think about the green dot that blinks every time you speak >>>>>>>>>>>>>>>> in the video pod: >>>>>>>>>>>>>>>> If it gets visible => one sync message >>>>>>>>>>>>>>>> If its get transparent => one sync message. >>>>>>>>>>>>>>>> If you have a quite good and sensitive micro it will flush >>>>>>>>>>>>>>>> 10 mabye 10 times per second. >>>>>>>>>>>>>>>> per 100 users in a room => 10 * 100 = 1000 queries in a >>>>>>>>>>>>>>>> SINGLE SECOND >>>>>>>>>>>>>>>> => that is just impossible !! >>>>>>>>>>>>>>>> And that is just a SINGLE videopod with 100 users watching. >>>>>>>>>>>>>>>> Now scale that up to 1000 concurrent rooms with 4x4 meetings >>>>>>>>>>>>>>>> where every >>>>>>>>>>>>>>>> user has micro turned on ?! Should we calc the number of >>>>>>>>>>>>>>>> database queries >>>>>>>>>>>>>>>> really?! >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Sorry we will not follow that route :) >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Sebastian >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> 2012/10/22 Maxim Solodovnik <[email protected]> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Previous solution was: >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> for (RoomClient rc: allClient) { >>>>>>>>>>>>>>>>> if (rc.getPublicSID().equals(_publicSID) { >>>>>>>>>>>>>>>>> return rc; >>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> + screen sharing clients were filtered same way. >>>>>>>>>>>>>>>>> Right now we can filter all sessions with 1 query this is >>>>>>>>>>>>>>>>> why the code can work faster (after minor changes in >>>>>>>>>>>>>>>>> iterating logic) >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> I'm not insist RoomClient should be DB object. But having >>>>>>>>>>>>>>>>> it as DB object was the only option to have user count in the >>>>>>>>>>>>>>>>> room (in case >>>>>>>>>>>>>>>>> Rooms are on the different servers). >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> I believe right now >>>>>>>>>>>>>>>>> org.apache.openmeetings.web.app.WebSession will be session >>>>>>>>>>>>>>>>> object. >>>>>>>>>>>>>>>>> I hope everything except audio and video will move to >>>>>>>>>>>>>>>>> Wicket :) >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> On Mon, Oct 22, 2012 at 2:33 PM, [email protected] < >>>>>>>>>>>>>>>>> [email protected]> wrote: >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Hi Maxim, >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> you can't persist on the argumentation that a HashMap >>>>>>>>>>>>>>>>>> stored in the memory is slower then doing a single query for >>>>>>>>>>>>>>>>>> every entry of >>>>>>>>>>>>>>>>>> the map ? >>>>>>>>>>>>>>>>>> Basicaly the previous implementation was a single HashMap. >>>>>>>>>>>>>>>>>> Getting a RoomClient from this map was: >>>>>>>>>>>>>>>>>> map.get($streamId) >>>>>>>>>>>>>>>>>> and now this single line is replaced by a Database query. >>>>>>>>>>>>>>>>>> The performance of this single line is ... I guess smaller >>>>>>>>>>>>>>>>>> then 1 >>>>>>>>>>>>>>>>>> millisecond. How can you say that a "Right now I think the >>>>>>>>>>>>>>>>>> current code >>>>>>>>>>>>>>>>>> should work faster or the same as previous one." :) >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> I guess you had some other requirements that made you >>>>>>>>>>>>>>>>>> implement this. >>>>>>>>>>>>>>>>>> For example for the clustering solution. >>>>>>>>>>>>>>>>>> However I also persist on my view: >>>>>>>>>>>>>>>>>> A database is _not_ the right place for storing session >>>>>>>>>>>>>>>>>> variables. This is simply a bad design decision that will >>>>>>>>>>>>>>>>>> cost a lot of >>>>>>>>>>>>>>>>>> performance in the future. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Could you explain why there is a need for having the >>>>>>>>>>>>>>>>>> RoomClient in the database? Maybe we can resolve those >>>>>>>>>>>>>>>>>> requirements >>>>>>>>>>>>>>>>>> differently so that we can have the RoomClient back in >>>>>>>>>>>>>>>>>> memory. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Sebastian >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> 2012/10/19 Maxim Solodovnik <[email protected]> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Sorry for double post. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Correct me if I'm wrong, but i think "Transient for XML >>>>>>>>>>>>>>>>>>> export/import" is not necessary since it doesn't have >>>>>>>>>>>>>>>>>>> @Element annotation >>>>>>>>>>>>>>>>>>> On Oct 19, 2012 9:59 PM, "Maxim Solodovnik" < >>>>>>>>>>>>>>>>>>> [email protected]> wrote: >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> RoomClient was mooved to the DB while I implemented >>>>>>>>>>>>>>>>>>>> cluster. >>>>>>>>>>>>>>>>>>>> Current changes only make the calls faster (since DB is >>>>>>>>>>>>>>>>>>>> quered only once) >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> I'll try to create couple of tests. Right now I think >>>>>>>>>>>>>>>>>>>> the current code should work faster or the same as >>>>>>>>>>>>>>>>>>>> previous one. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Old code did lots of full filterings of RommsClient >>>>>>>>>>>>>>>>>>>> hash map to get subset required. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> I tests will show I'm wrong on this I'll try to tune up >>>>>>>>>>>>>>>>>>>> openjpa cache and if it doesn't help will split RoomClient >>>>>>>>>>>>>>>>>>>> to the couple of >>>>>>>>>>>>>>>>>>>> objects and/or will create hashtable in parallel to speed >>>>>>>>>>>>>>>>>>>> up things. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> But I hope everything is not so slow since these >>>>>>>>>>>>>>>>>>>> changes are present in 2.0 and nobody reports performance >>>>>>>>>>>>>>>>>>>> degradation. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Sorry for typos, I'm from mobile phone >>>>>>>>>>>>>>>>>>>> On Oct 19, 2012 9:11 PM, "[email protected]" < >>>>>>>>>>>>>>>>>>>> [email protected]> wrote: >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> I guess this happened lately in trunk. >>>>>>>>>>>>>>>>>>>>> How are we the in the future planning to determine the >>>>>>>>>>>>>>>>>>>>> current users in the room. >>>>>>>>>>>>>>>>>>>>> Session or database based? >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> I ask that critical as some queries require to sync >>>>>>>>>>>>>>>>>>>>> messages to all clients of a room. >>>>>>>>>>>>>>>>>>>>> This can happen 1000 times in a single second if you >>>>>>>>>>>>>>>>>>>>> think about having up to 1000 concurrent user sessions. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> For example: >>>>>>>>>>>>>>>>>>>>> ScopeApplicationAdapter::syncMessageToCurrentScope(String >>>>>>>>>>>>>>>>>>>>> remoteMethodName, Object newMessage, boolean sendSelf, >>>>>>>>>>>>>>>>>>>>> boolean sendScreen) >>>>>>>>>>>>>>>>>>>>> => Collection<Set<IConnection>> conCollection = >>>>>>>>>>>>>>>>>>>>> current.getScope() >>>>>>>>>>>>>>>>>>>>> .getConnections(); >>>>>>>>>>>>>>>>>>>>> ==> iterates through all connection of the scope. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Now the new thing is that for every connection you >>>>>>>>>>>>>>>>>>>>> will create a query for the RoomClient Object. >>>>>>>>>>>>>>>>>>>>> This is simply impossible. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> We want to scale up to 1000 concurrent user sessions >>>>>>>>>>>>>>>>>>>>> and more. >>>>>>>>>>>>>>>>>>>>> The RoomClient is a typical Session object and it >>>>>>>>>>>>>>>>>>>>> should stay in the session. >>>>>>>>>>>>>>>>>>>>> It is the same issue like with the WhiteboardObject. >>>>>>>>>>>>>>>>>>>>> We are making a real time application, there is no >>>>>>>>>>>>>>>>>>>>> chance to run queries in sync methods. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Can we find some consens here? I know you must have >>>>>>>>>>>>>>>>>>>>> refactored already a lot but I strictly did implement >>>>>>>>>>>>>>>>>>>>> zero db related stuff >>>>>>>>>>>>>>>>>>>>> in sync methods. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> There might be a chance for some events to trigger db >>>>>>>>>>>>>>>>>>>>> actions.However I don't think having two times the >>>>>>>>>>>>>>>>>>>>> RoomClient stored (one >>>>>>>>>>>>>>>>>>>>> time session, second time database) makes sense. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> What are you thoughts on this? >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Sebastian >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> 2012/10/19 [email protected] < >>>>>>>>>>>>>>>>>>>>> [email protected]> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Hi Maxim, >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> I don't understand this new code in the Rooms Entity: >>>>>>>>>>>>>>>>>>>>>> @OneToMany(fetch = FetchType.LAZY) >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> @JoinColumn(name = "room_id") >>>>>>>>>>>>>>>>>>>>>> private List<RoomClient> currentusers; >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> We calc the current users online by iterating through >>>>>>>>>>>>>>>>>>>>>> the Red5 Connections. >>>>>>>>>>>>>>>>>>>>>> In which OpenMeetings version was it changed? >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> I guess you can set it Transient for XML >>>>>>>>>>>>>>>>>>>>>> export/import. So maybe annotate it with: >>>>>>>>>>>>>>>>>>>>>> @org.simpleframework.xml.Transient >>>>>>>>>>>>>>>>>>>>>> same like roomOrganisations. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Sebastian >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> 2012/10/19 <[email protected]> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Author: solomax >>>>>>>>>>>>>>>>>>>>>>> Date: Fri Oct 19 12:39:38 2012 >>>>>>>>>>>>>>>>>>>>>>> New Revision: 1400075 >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> URL: >>>>>>>>>>>>>>>>>>>>>>> http://svn.apache.org/viewvc?rev=1400075&view=rev >>>>>>>>>>>>>>>>>>>>>>> Log: >>>>>>>>>>>>>>>>>>>>>>> Wicket: calendar form is improved >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Modified: >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/data/conference/RoomDAO.java >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/persistence/beans/rooms/Rooms.java >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarForm.java >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarPanel.html >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarPanel.java >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Modified: >>>>>>>>>>>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/data/conference/RoomDAO.java >>>>>>>>>>>>>>>>>>>>>>> URL: >>>>>>>>>>>>>>>>>>>>>>> http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/data/conference/RoomDAO.java?rev=1400075&r1=1400074&r2=1400075&view=diff >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> ============================================================================== >>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/data/conference/RoomDAO.java >>>>>>>>>>>>>>>>>>>>>>> (original) >>>>>>>>>>>>>>>>>>>>>>> +++ >>>>>>>>>>>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/data/conference/RoomDAO.java >>>>>>>>>>>>>>>>>>>>>>> Fri Oct 19 12:39:38 2012 >>>>>>>>>>>>>>>>>>>>>>> @@ -76,6 +76,24 @@ public class RoomDAO implements >>>>>>>>>>>>>>>>>>>>>>> OmDAO<Ro >>>>>>>>>>>>>>>>>>>>>>> return q.getSingleResult(); >>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> + public List<Rooms> getPublicRooms() { >>>>>>>>>>>>>>>>>>>>>>> + //TypedQuery<Rooms> q = >>>>>>>>>>>>>>>>>>>>>>> em.createNamedQuery("getNondeletedRooms", Rooms.class); >>>>>>>>>>>>>>>>>>>>>>> + TypedQuery<Rooms> q = em.createQuery( >>>>>>>>>>>>>>>>>>>>>>> + "SELECT r from Rooms >>>>>>>>>>>>>>>>>>>>>>> r LEFT JOIN FETCH r.currentusers WHERE r.ispublic= true >>>>>>>>>>>>>>>>>>>>>>> and r.deleted= >>>>>>>>>>>>>>>>>>>>>>> false ORDER BY r.name ASC", Rooms.class); >>>>>>>>>>>>>>>>>>>>>>> + return q.getResultList(); >>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> + public List<Rooms> getOrganisationRooms(long >>>>>>>>>>>>>>>>>>>>>>> orgId) { >>>>>>>>>>>>>>>>>>>>>>> + TypedQuery<Rooms> q = em.createQuery( >>>>>>>>>>>>>>>>>>>>>>> + "SELECT DISTINCT >>>>>>>>>>>>>>>>>>>>>>> c.room FROM Rooms_Organisation c LEFT JOIN FETCH c.room >>>>>>>>>>>>>>>>>>>>>>> LEFT JOIN FETCH >>>>>>>>>>>>>>>>>>>>>>> c.room.currentusers " >>>>>>>>>>>>>>>>>>>>>>> + + "WHERE >>>>>>>>>>>>>>>>>>>>>>> c.organisation.organisation_id = :orgId " >>>>>>>>>>>>>>>>>>>>>>> + + "AND c.deleted = false AND >>>>>>>>>>>>>>>>>>>>>>> c.room.deleted = false " >>>>>>>>>>>>>>>>>>>>>>> + + "AND c.organisation.deleted = >>>>>>>>>>>>>>>>>>>>>>> false " >>>>>>>>>>>>>>>>>>>>>>> + + "ORDER BY c.room.name ASC", >>>>>>>>>>>>>>>>>>>>>>> Rooms.class); >>>>>>>>>>>>>>>>>>>>>>> + q.setParameter("orgId", orgId); >>>>>>>>>>>>>>>>>>>>>>> + return q.getResultList(); >>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> public Rooms update(Rooms entity, long >>>>>>>>>>>>>>>>>>>>>>> userId) { >>>>>>>>>>>>>>>>>>>>>>> if (entity.getRooms_id() == null) { >>>>>>>>>>>>>>>>>>>>>>> /* Red5SIP integration >>>>>>>>>>>>>>>>>>>>>>> *******************************************************************************/ >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Modified: >>>>>>>>>>>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/persistence/beans/rooms/Rooms.java >>>>>>>>>>>>>>>>>>>>>>> URL: >>>>>>>>>>>>>>>>>>>>>>> http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/persistence/beans/rooms/Rooms.java?rev=1400075&r1=1400074&r2=1400075&view=diff >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> ============================================================================== >>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/persistence/beans/rooms/Rooms.java >>>>>>>>>>>>>>>>>>>>>>> (original) >>>>>>>>>>>>>>>>>>>>>>> +++ >>>>>>>>>>>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/persistence/beans/rooms/Rooms.java >>>>>>>>>>>>>>>>>>>>>>> Fri Oct 19 12:39:38 2012 >>>>>>>>>>>>>>>>>>>>>>> @@ -38,7 +38,6 @@ import >>>>>>>>>>>>>>>>>>>>>>> javax.persistence.NamedQuery; >>>>>>>>>>>>>>>>>>>>>>> import javax.persistence.OneToMany; >>>>>>>>>>>>>>>>>>>>>>> import javax.persistence.OneToOne; >>>>>>>>>>>>>>>>>>>>>>> import javax.persistence.Table; >>>>>>>>>>>>>>>>>>>>>>> -import javax.persistence.Transient; >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> import >>>>>>>>>>>>>>>>>>>>>>> org.apache.openjpa.persistence.ElementDependent; >>>>>>>>>>>>>>>>>>>>>>> import >>>>>>>>>>>>>>>>>>>>>>> org.apache.openmeetings.persistence.beans.OmEntity; >>>>>>>>>>>>>>>>>>>>>>> @@ -69,7 +68,6 @@ public class Rooms implements >>>>>>>>>>>>>>>>>>>>>>> Serializab >>>>>>>>>>>>>>>>>>>>>>> private String name; >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> @Lob >>>>>>>>>>>>>>>>>>>>>>> - // @Basic(fetch=FetchType.LAZY) >>>>>>>>>>>>>>>>>>>>>>> @Column(name = "comment_field") >>>>>>>>>>>>>>>>>>>>>>> @Element(data = true, required = false) >>>>>>>>>>>>>>>>>>>>>>> private String comment; >>>>>>>>>>>>>>>>>>>>>>> @@ -217,10 +215,8 @@ public class Rooms implements >>>>>>>>>>>>>>>>>>>>>>> Serializab >>>>>>>>>>>>>>>>>>>>>>> @org.simpleframework.xml.Transient >>>>>>>>>>>>>>>>>>>>>>> private List<Rooms_Organisation> >>>>>>>>>>>>>>>>>>>>>>> roomOrganisations = new ArrayList<Rooms_Organisation>(); >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> - /* >>>>>>>>>>>>>>>>>>>>>>> - * Non persistent attributes >>>>>>>>>>>>>>>>>>>>>>> - */ >>>>>>>>>>>>>>>>>>>>>>> - @Transient >>>>>>>>>>>>>>>>>>>>>>> + @OneToMany(fetch = FetchType.LAZY) >>>>>>>>>>>>>>>>>>>>>>> + @JoinColumn(name = "room_id") >>>>>>>>>>>>>>>>>>>>>>> private List<RoomClient> currentusers; >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> public String getComment() { >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Modified: >>>>>>>>>>>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarForm.java >>>>>>>>>>>>>>>>>>>>>>> URL: >>>>>>>>>>>>>>>>>>>>>>> http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarForm.java?rev=1400075&r1=1400074&r2=1400075&view=diff >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> ============================================================================== >>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarForm.java >>>>>>>>>>>>>>>>>>>>>>> (original) >>>>>>>>>>>>>>>>>>>>>>> +++ >>>>>>>>>>>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarForm.java >>>>>>>>>>>>>>>>>>>>>>> Fri Oct 19 12:39:38 2012 >>>>>>>>>>>>>>>>>>>>>>> @@ -18,14 +18,36 @@ >>>>>>>>>>>>>>>>>>>>>>> */ >>>>>>>>>>>>>>>>>>>>>>> package >>>>>>>>>>>>>>>>>>>>>>> org.apache.openmeetings.web.components.user.calendar; >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> +import java.util.ArrayList; >>>>>>>>>>>>>>>>>>>>>>> +import java.util.List; >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> +import >>>>>>>>>>>>>>>>>>>>>>> org.apache.openmeetings.data.calendar.daos.AppointmentReminderTypDaoImpl; >>>>>>>>>>>>>>>>>>>>>>> +import >>>>>>>>>>>>>>>>>>>>>>> org.apache.openmeetings.data.conference.RoomDAO; >>>>>>>>>>>>>>>>>>>>>>> +import >>>>>>>>>>>>>>>>>>>>>>> org.apache.openmeetings.data.conference.Roommanagement; >>>>>>>>>>>>>>>>>>>>>>> +import >>>>>>>>>>>>>>>>>>>>>>> org.apache.openmeetings.data.user.dao.UsersDaoImpl; >>>>>>>>>>>>>>>>>>>>>>> import >>>>>>>>>>>>>>>>>>>>>>> org.apache.openmeetings.persistence.beans.calendar.Appointment; >>>>>>>>>>>>>>>>>>>>>>> +import >>>>>>>>>>>>>>>>>>>>>>> org.apache.openmeetings.persistence.beans.calendar.AppointmentReminderTyps; >>>>>>>>>>>>>>>>>>>>>>> +import >>>>>>>>>>>>>>>>>>>>>>> org.apache.openmeetings.persistence.beans.domain.Organisation_Users; >>>>>>>>>>>>>>>>>>>>>>> +import >>>>>>>>>>>>>>>>>>>>>>> org.apache.openmeetings.persistence.beans.rooms.RoomTypes; >>>>>>>>>>>>>>>>>>>>>>> +import >>>>>>>>>>>>>>>>>>>>>>> org.apache.openmeetings.persistence.beans.rooms.Rooms; >>>>>>>>>>>>>>>>>>>>>>> +import org.apache.openmeetings.web.app.Application; >>>>>>>>>>>>>>>>>>>>>>> +import org.apache.openmeetings.web.app.WebSession; >>>>>>>>>>>>>>>>>>>>>>> +import org.apache.wicket.ajax.AjaxRequestTarget; >>>>>>>>>>>>>>>>>>>>>>> +import >>>>>>>>>>>>>>>>>>>>>>> org.apache.wicket.ajax.markup.html.form.AjaxCheckBox; >>>>>>>>>>>>>>>>>>>>>>> +import >>>>>>>>>>>>>>>>>>>>>>> org.apache.wicket.extensions.yui.calendar.DateTimeField; >>>>>>>>>>>>>>>>>>>>>>> +import >>>>>>>>>>>>>>>>>>>>>>> org.apache.wicket.markup.html.form.ChoiceRenderer; >>>>>>>>>>>>>>>>>>>>>>> +import >>>>>>>>>>>>>>>>>>>>>>> org.apache.wicket.markup.html.form.DropDownChoice; >>>>>>>>>>>>>>>>>>>>>>> import org.apache.wicket.markup.html.form.Form; >>>>>>>>>>>>>>>>>>>>>>> +import >>>>>>>>>>>>>>>>>>>>>>> org.apache.wicket.markup.html.form.PasswordTextField; >>>>>>>>>>>>>>>>>>>>>>> import >>>>>>>>>>>>>>>>>>>>>>> org.apache.wicket.markup.html.form.RequiredTextField; >>>>>>>>>>>>>>>>>>>>>>> import org.apache.wicket.markup.html.form.TextArea; >>>>>>>>>>>>>>>>>>>>>>> +import org.apache.wicket.markup.html.form.TextField; >>>>>>>>>>>>>>>>>>>>>>> import org.apache.wicket.model.IModel; >>>>>>>>>>>>>>>>>>>>>>> +import org.apache.wicket.model.PropertyModel; >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> public class CalendarForm extends Form<Appointment> >>>>>>>>>>>>>>>>>>>>>>> { >>>>>>>>>>>>>>>>>>>>>>> private static final long serialVersionUID = >>>>>>>>>>>>>>>>>>>>>>> -1764738237821487526L; >>>>>>>>>>>>>>>>>>>>>>> + private boolean createRoom = true; >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> public CalendarForm(String id, >>>>>>>>>>>>>>>>>>>>>>> IModel<Appointment> model) { >>>>>>>>>>>>>>>>>>>>>>> super(id, model); >>>>>>>>>>>>>>>>>>>>>>> @@ -33,5 +55,71 @@ public class CalendarForm extends >>>>>>>>>>>>>>>>>>>>>>> Form<A >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> add(new >>>>>>>>>>>>>>>>>>>>>>> RequiredTextField<String>("appointmentName")); >>>>>>>>>>>>>>>>>>>>>>> add(new >>>>>>>>>>>>>>>>>>>>>>> TextArea<String>("appointmentDescription")); >>>>>>>>>>>>>>>>>>>>>>> + add(new >>>>>>>>>>>>>>>>>>>>>>> TextField<String>("appointmentLocation")); >>>>>>>>>>>>>>>>>>>>>>> + add(new >>>>>>>>>>>>>>>>>>>>>>> DateTimeField("appointmentStarttime")); >>>>>>>>>>>>>>>>>>>>>>> + add(new >>>>>>>>>>>>>>>>>>>>>>> DateTimeField("appointmentEndtime")); >>>>>>>>>>>>>>>>>>>>>>> + final PasswordTextField pwd = new >>>>>>>>>>>>>>>>>>>>>>> PasswordTextField("password"); >>>>>>>>>>>>>>>>>>>>>>> + pwd.setEnabled(isPwdProtected()); >>>>>>>>>>>>>>>>>>>>>>> + pwd.setOutputMarkupId(true); >>>>>>>>>>>>>>>>>>>>>>> + add(pwd); >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> + add(new >>>>>>>>>>>>>>>>>>>>>>> DropDownChoice<AppointmentReminderTyps>( >>>>>>>>>>>>>>>>>>>>>>> + "remind" >>>>>>>>>>>>>>>>>>>>>>> + , >>>>>>>>>>>>>>>>>>>>>>> Application.getBean(AppointmentReminderTypDaoImpl.class).getAppointmentReminderTypList() >>>>>>>>>>>>>>>>>>>>>>> + , new >>>>>>>>>>>>>>>>>>>>>>> ChoiceRenderer<AppointmentReminderTyps>("name", >>>>>>>>>>>>>>>>>>>>>>> "typId"))); >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> + final DropDownChoice<RoomTypes> >>>>>>>>>>>>>>>>>>>>>>> roomType = new DropDownChoice<RoomTypes>( >>>>>>>>>>>>>>>>>>>>>>> + "room.roomtype" >>>>>>>>>>>>>>>>>>>>>>> + , >>>>>>>>>>>>>>>>>>>>>>> Application.getBean(Roommanagement.class).getAllRoomTypes() >>>>>>>>>>>>>>>>>>>>>>> + , new >>>>>>>>>>>>>>>>>>>>>>> ChoiceRenderer<RoomTypes>("name", "roomtypes_id")); >>>>>>>>>>>>>>>>>>>>>>> + roomType.setEnabled(createRoom); >>>>>>>>>>>>>>>>>>>>>>> + roomType.setOutputMarkupId(true); >>>>>>>>>>>>>>>>>>>>>>> + add(roomType); >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> + final DropDownChoice<Rooms> room = >>>>>>>>>>>>>>>>>>>>>>> new DropDownChoice<Rooms>( >>>>>>>>>>>>>>>>>>>>>>> + "room" >>>>>>>>>>>>>>>>>>>>>>> + , getRoomList() >>>>>>>>>>>>>>>>>>>>>>> + , new >>>>>>>>>>>>>>>>>>>>>>> ChoiceRenderer<Rooms>("name", "rooms_id")); >>>>>>>>>>>>>>>>>>>>>>> + room.setEnabled(!createRoom); >>>>>>>>>>>>>>>>>>>>>>> + room.setOutputMarkupId(true); >>>>>>>>>>>>>>>>>>>>>>> + add(room); >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> + add(new AjaxCheckBox("createRoom", >>>>>>>>>>>>>>>>>>>>>>> new PropertyModel<Boolean>(this, "createRoom")) { >>>>>>>>>>>>>>>>>>>>>>> + private static final long >>>>>>>>>>>>>>>>>>>>>>> serialVersionUID = -3743113990890386035L; >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> + @Override >>>>>>>>>>>>>>>>>>>>>>> + protected void >>>>>>>>>>>>>>>>>>>>>>> onUpdate(AjaxRequestTarget target) { >>>>>>>>>>>>>>>>>>>>>>> + createRoom = >>>>>>>>>>>>>>>>>>>>>>> getConvertedInput(); >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> target.add(roomType.setEnabled(createRoom), >>>>>>>>>>>>>>>>>>>>>>> room.setEnabled(!createRoom)); >>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>> + }); >>>>>>>>>>>>>>>>>>>>>>> + add(new >>>>>>>>>>>>>>>>>>>>>>> AjaxCheckBox("isPasswordProtected") { >>>>>>>>>>>>>>>>>>>>>>> + private static final long >>>>>>>>>>>>>>>>>>>>>>> serialVersionUID = 6041200584296439976L; >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> + @Override >>>>>>>>>>>>>>>>>>>>>>> + protected void >>>>>>>>>>>>>>>>>>>>>>> onUpdate(AjaxRequestTarget target) { >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> CalendarForm.this.getModelObject().setIsPasswordProtected(getConvertedInput()); >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> pwd.setEnabled(isPwdProtected()); >>>>>>>>>>>>>>>>>>>>>>> + target.add(pwd); >>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>> + }); >>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> + private boolean isPwdProtected() { >>>>>>>>>>>>>>>>>>>>>>> + return >>>>>>>>>>>>>>>>>>>>>>> Boolean.TRUE.equals(getModelObject().getIsPasswordProtected()); >>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> + private List<Rooms> getRoomList() { >>>>>>>>>>>>>>>>>>>>>>> + //FIXME need to be reviewed >>>>>>>>>>>>>>>>>>>>>>> + List<Rooms> result = new >>>>>>>>>>>>>>>>>>>>>>> ArrayList<Rooms>(); >>>>>>>>>>>>>>>>>>>>>>> + RoomDAO dao = >>>>>>>>>>>>>>>>>>>>>>> Application.getBean(RoomDAO.class); >>>>>>>>>>>>>>>>>>>>>>> + result.addAll(dao.getPublicRooms()); >>>>>>>>>>>>>>>>>>>>>>> + for (Organisation_Users ou : >>>>>>>>>>>>>>>>>>>>>>> Application.getBean(UsersDaoImpl.class).get(WebSession.getUserId()).getOrganisation_users()) >>>>>>>>>>>>>>>>>>>>>>> { >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> result.addAll(dao.getOrganisationRooms(ou.getOrganisation().getOrganisation_id())); >>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>> + if (getModelObject().getRoom() != >>>>>>>>>>>>>>>>>>>>>>> null && getModelObject().getRoom().getAppointment()) { >>>>>>>>>>>>>>>>>>>>>>> //FIXME review >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> result.add(getModelObject().getRoom()); >>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>> + return result; >>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Modified: >>>>>>>>>>>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarPanel.html >>>>>>>>>>>>>>>>>>>>>>> URL: >>>>>>>>>>>>>>>>>>>>>>> http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarPanel.html?rev=1400075&r1=1400074&r2=1400075&view=diff >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> ============================================================================== >>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarPanel.html >>>>>>>>>>>>>>>>>>>>>>> (original) >>>>>>>>>>>>>>>>>>>>>>> +++ >>>>>>>>>>>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarPanel.html >>>>>>>>>>>>>>>>>>>>>>> Fri Oct 19 12:39:38 2012 >>>>>>>>>>>>>>>>>>>>>>> @@ -71,7 +71,7 @@ >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> $('#appointment').dialog({ >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> closeOnEscape: true >>>>>>>>>>>>>>>>>>>>>>> , resizable: >>>>>>>>>>>>>>>>>>>>>>> true >>>>>>>>>>>>>>>>>>>>>>> - , width: 400 >>>>>>>>>>>>>>>>>>>>>>> + , width: 450 >>>>>>>>>>>>>>>>>>>>>>> , autoOpen: >>>>>>>>>>>>>>>>>>>>>>> false >>>>>>>>>>>>>>>>>>>>>>> , modal: true >>>>>>>>>>>>>>>>>>>>>>> }); >>>>>>>>>>>>>>>>>>>>>>> @@ -89,53 +89,55 @@ >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> <td><wicket:ommessage key="572" /></td> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> <td><input type="text" wicket:id="appointmentName" >>>>>>>>>>>>>>>>>>>>>>> /></td> >>>>>>>>>>>>>>>>>>>>>>> </tr> >>>>>>>>>>>>>>>>>>>>>>> - <!-- tr> >>>>>>>>>>>>>>>>>>>>>>> - >>>>>>>>>>>>>>>>>>>>>>> <td> </td> >>>>>>>>>>>>>>>>>>>>>>> - <td> >>>>>>>>>>>>>>>>>>>>>>> - >>>>>>>>>>>>>>>>>>>>>>> <wicket:ommessage key="570" /><input type="text" >>>>>>>>>>>>>>>>>>>>>>> wicket:id="appointmentStarttime" /> >>>>>>>>>>>>>>>>>>>>>>> - >>>>>>>>>>>>>>>>>>>>>>> <wicket:ommessage key="571" /><input type="text" >>>>>>>>>>>>>>>>>>>>>>> wicket:id="appointmentEndtime" /> >>>>>>>>>>>>>>>>>>>>>>> - </td> >>>>>>>>>>>>>>>>>>>>>>> + <tr> >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> <td><wicket:ommessage key="570" /></td> >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> <td><span wicket:id="appointmentStarttime"></span></td> >>>>>>>>>>>>>>>>>>>>>>> + </tr> >>>>>>>>>>>>>>>>>>>>>>> + <tr> >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> <td><wicket:ommessage key="571" /></td> >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> <td><span wicket:id="appointmentEndtime"></span></td> >>>>>>>>>>>>>>>>>>>>>>> </tr> >>>>>>>>>>>>>>>>>>>>>>> <tr> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> <td><wicket:ommessage key="565" /></td> >>>>>>>>>>>>>>>>>>>>>>> - >>>>>>>>>>>>>>>>>>>>>>> <td><select wicket:id="notification" ></select></td> >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> <td><select wicket:id="remind" ></select></td> >>>>>>>>>>>>>>>>>>>>>>> </tr> >>>>>>>>>>>>>>>>>>>>>>> <tr> >>>>>>>>>>>>>>>>>>>>>>> <td >>>>>>>>>>>>>>>>>>>>>>> colspan="2"><input type="checkbox" >>>>>>>>>>>>>>>>>>>>>>> wicket:id="createRoom" >>>>>>>>>>>>>>>>>>>>>>> /><wicket:ommessage key="1509" /></td> >>>>>>>>>>>>>>>>>>>>>>> </tr> >>>>>>>>>>>>>>>>>>>>>>> <tr> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> <td><wicket:ommessage key="619" /></td> >>>>>>>>>>>>>>>>>>>>>>> - >>>>>>>>>>>>>>>>>>>>>>> <td><select wicket:id="roomType" ></select></td> >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> <td><select wicket:id="room.roomtype" ></select></td> >>>>>>>>>>>>>>>>>>>>>>> </tr> >>>>>>>>>>>>>>>>>>>>>>> <tr> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> <td><wicket:ommessage key="406" /></td> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> <td><select wicket:id="room" ></select></td> >>>>>>>>>>>>>>>>>>>>>>> </tr> >>>>>>>>>>>>>>>>>>>>>>> <tr> >>>>>>>>>>>>>>>>>>>>>>> - <td >>>>>>>>>>>>>>>>>>>>>>> colspan="2"><input type="checkbox" >>>>>>>>>>>>>>>>>>>>>>> wicket:id="isPasswordProtected" >>>>>>>>>>>>>>>>>>>>>>> /><wicket:ommessage key="1509" /></td> >>>>>>>>>>>>>>>>>>>>>>> + <td >>>>>>>>>>>>>>>>>>>>>>> colspan="2"><input type="checkbox" >>>>>>>>>>>>>>>>>>>>>>> wicket:id="isPasswordProtected" >>>>>>>>>>>>>>>>>>>>>>> /><wicket:ommessage key="524" /></td> >>>>>>>>>>>>>>>>>>>>>>> </tr> >>>>>>>>>>>>>>>>>>>>>>> <tr> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> <td><wicket:ommessage key="525" /></td> >>>>>>>>>>>>>>>>>>>>>>> - >>>>>>>>>>>>>>>>>>>>>>> <td><input type="text" wicket:id="password" /></td> >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> <td><input type="password" wicket:id="password" /></td> >>>>>>>>>>>>>>>>>>>>>>> </tr> >>>>>>>>>>>>>>>>>>>>>>> <tr> >>>>>>>>>>>>>>>>>>>>>>> <td >>>>>>>>>>>>>>>>>>>>>>> colspan="2"><wicket:ommessage key="1445" /></td> >>>>>>>>>>>>>>>>>>>>>>> </tr> >>>>>>>>>>>>>>>>>>>>>>> + <!-- >>>>>>>>>>>>>>>>>>>>>>> <tr> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> <td><wicket:ommessage key="803" /></td> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> <td><select wicket:id="meetingMember" ></select></td> >>>>>>>>>>>>>>>>>>>>>>> - </tr> >>>>>>>>>>>>>>>>>>>>>>> + </tr --> >>>>>>>>>>>>>>>>>>>>>>> <tr> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> <td><wicket:ommessage key="569" /></td> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> <td><input type="text" wicket:id="appointmentLocation" >>>>>>>>>>>>>>>>>>>>>>> /></td> >>>>>>>>>>>>>>>>>>>>>>> - </tr--> >>>>>>>>>>>>>>>>>>>>>>> + </tr> >>>>>>>>>>>>>>>>>>>>>>> <tr> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> <td><wicket:ommessage key="573" /></td> >>>>>>>>>>>>>>>>>>>>>>> - >>>>>>>>>>>>>>>>>>>>>>> <td><input type="text" >>>>>>>>>>>>>>>>>>>>>>> wicket:id="appointmentDescription" /></td> >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> <td><textarea >>>>>>>>>>>>>>>>>>>>>>> wicket:id="appointmentDescription"></textarea></td> >>>>>>>>>>>>>>>>>>>>>>> </tr> >>>>>>>>>>>>>>>>>>>>>>> <!-- tr> >>>>>>>>>>>>>>>>>>>>>>> <td >>>>>>>>>>>>>>>>>>>>>>> colspan="2" style="text-align: right"><input >>>>>>>>>>>>>>>>>>>>>>> type="button" wicket:id="save" >>>>>>>>>>>>>>>>>>>>>>> /><input type="button" wicket:id="cancel" /></td> >>>>>>>>>>>>>>>>>>>>>>> - </tr--> >>>>>>>>>>>>>>>>>>>>>>> + </tr --> >>>>>>>>>>>>>>>>>>>>>>> </table> >>>>>>>>>>>>>>>>>>>>>>> </form> >>>>>>>>>>>>>>>>>>>>>>> </div> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Modified: >>>>>>>>>>>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarPanel.java >>>>>>>>>>>>>>>>>>>>>>> URL: >>>>>>>>>>>>>>>>>>>>>>> http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarPanel.java?rev=1400075&r1=1400074&r2=1400075&view=diff >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> ============================================================================== >>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarPanel.java >>>>>>>>>>>>>>>>>>>>>>> (original) >>>>>>>>>>>>>>>>>>>>>>> +++ >>>>>>>>>>>>>>>>>>>>>>> incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/user/calendar/CalendarPanel.java >>>>>>>>>>>>>>>>>>>>>>> Fri Oct 19 12:39:38 2012 >>>>>>>>>>>>>>>>>>>>>>> @@ -150,6 +150,9 @@ public class CalendarPanel >>>>>>>>>>>>>>>>>>>>>>> extends UserP >>>>>>>>>>>>>>>>>>>>>>> Calendar end = >>>>>>>>>>>>>>>>>>>>>>> WebSession.getCalendar(); >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> end.setTimeInMillis(getRequestCycle().getRequest().getRequestParameters().getParameterValue("_end").toLong()); >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> + if >>>>>>>>>>>>>>>>>>>>>>> (start.equals(end)) { >>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>> end.add(Calendar.HOUR_OF_DAY, 1); >>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>> Appointment a = new >>>>>>>>>>>>>>>>>>>>>>> Appointment(); >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> a.setAppointmentStarttime(start.getTime()); >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> a.setAppointmentEndtime(end.getTime()); >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> -- >>>>>>>>>>>>>>>>>>>>>> Sebastian Wagner >>>>>>>>>>>>>>>>>>>>>> https://twitter.com/#!/dead_lock >>>>>>>>>>>>>>>>>>>>>> http://www.webbase-design.de >>>>>>>>>>>>>>>>>>>>>> http://www.wagner-sebastian.com >>>>>>>>>>>>>>>>>>>>>> [email protected] >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> -- >>>>>>>>>>>>>>>>>>>>> Sebastian Wagner >>>>>>>>>>>>>>>>>>>>> https://twitter.com/#!/dead_lock >>>>>>>>>>>>>>>>>>>>> http://www.webbase-design.de >>>>>>>>>>>>>>>>>>>>> http://www.wagner-sebastian.com >>>>>>>>>>>>>>>>>>>>> [email protected] >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> -- >>>>>>>>>>>>>>>>>> Sebastian Wagner >>>>>>>>>>>>>>>>>> https://twitter.com/#!/dead_lock >>>>>>>>>>>>>>>>>> http://www.webbase-design.de >>>>>>>>>>>>>>>>>> http://www.wagner-sebastian.com >>>>>>>>>>>>>>>>>> [email protected] >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> -- >>>>>>>>>>>>>>>>> WBR >>>>>>>>>>>>>>>>> Maxim aka solomax >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> -- >>>>>>>>>>>>>>>> Sebastian Wagner >>>>>>>>>>>>>>>> https://twitter.com/#!/dead_lock >>>>>>>>>>>>>>>> http://www.webbase-design.de >>>>>>>>>>>>>>>> http://www.wagner-sebastian.com >>>>>>>>>>>>>>>> [email protected] >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> -- >>>>>>>>>>>>>>> WBR >>>>>>>>>>>>>>> Maxim aka solomax >>>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> -- >>>>>>>>>>>>>> Sebastian Wagner >>>>>>>>>>>>>> https://twitter.com/#!/dead_lock >>>>>>>>>>>>>> http://www.webbase-design.de >>>>>>>>>>>>>> http://www.wagner-sebastian.com >>>>>>>>>>>>>> [email protected] >>>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> -- >>>>>>>>>>>>> WBR >>>>>>>>>>>>> Maxim aka solomax >>>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> -- >>>>>>>>>>>> Sebastian Wagner >>>>>>>>>>>> https://twitter.com/#!/dead_lock >>>>>>>>>>>> http://www.webbase-design.de >>>>>>>>>>>> http://www.wagner-sebastian.com >>>>>>>>>>>> [email protected] >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> -- >>>>>>>>>>> Sebastian Wagner >>>>>>>>>>> https://twitter.com/#!/dead_lock >>>>>>>>>>> http://www.webbase-design.de >>>>>>>>>>> http://www.wagner-sebastian.com >>>>>>>>>>> [email protected] >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> -- >>>>>>>>>> WBR >>>>>>>>>> Maxim aka solomax >>>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> -- >>>>>>>>> Sebastian Wagner >>>>>>>>> https://twitter.com/#!/dead_lock >>>>>>>>> http://www.webbase-design.de >>>>>>>>> http://www.wagner-sebastian.com >>>>>>>>> [email protected] >>>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> -- >>>>>>>> WBR >>>>>>>> Maxim aka solomax >>>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> -- >>>>>>> Sebastian Wagner >>>>>>> https://twitter.com/#!/dead_lock >>>>>>> http://www.webbase-design.de >>>>>>> http://www.wagner-sebastian.com >>>>>>> [email protected] >>>>>>> >>>>>> >>>>>> >>>>>> >>>>>> -- >>>>>> WBR >>>>>> Maxim aka solomax >>>>>> >>>>> >>>>> >>>>> >>>>> -- >>>>> Sebastian Wagner >>>>> https://twitter.com/#!/dead_lock >>>>> http://www.webbase-design.de >>>>> http://www.wagner-sebastian.com >>>>> [email protected] >>>>> >>>> >>>> >>>> >>>> -- >>>> WBR >>>> Maxim aka solomax >>>> >>> >>> >>> >>> -- >>> Sebastian Wagner >>> https://twitter.com/#!/dead_lock >>> http://www.webbase-design.de >>> http://www.wagner-sebastian.com >>> [email protected] >>> >> >> >> >> -- >> Sebastian Wagner >> https://twitter.com/#!/dead_lock >> http://www.webbase-design.de >> http://www.wagner-sebastian.com >> [email protected] >> > > > > -- > WBR > Maxim aka solomax > -- Sebastian Wagner https://twitter.com/#!/dead_lock http://www.webbase-design.de http://www.wagner-sebastian.com [email protected]
