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]
