1 29 30 package nextapp.echo2.webrender.service; 31 32 import java.io.ByteArrayInputStream ; 33 import java.io.ByteArrayOutputStream ; 34 import java.io.IOException ; 35 import java.io.InputStream ; 36 import java.util.HashMap ; 37 import java.util.Map ; 38 39 import javax.servlet.http.HttpServletRequest ; 40 41 import org.w3c.dom.Document ; 42 import org.w3c.dom.Element ; 43 import org.xml.sax.SAXException ; 44 45 import nextapp.echo2.webrender.ClientAnalyzerProcessor; 46 import nextapp.echo2.webrender.Connection; 47 import nextapp.echo2.webrender.ContentType; 48 import nextapp.echo2.webrender.ServerMessage; 49 import nextapp.echo2.webrender.Service; 50 import nextapp.echo2.webrender.UserInstance; 51 import nextapp.echo2.webrender.UserInstanceUpdateManager; 52 import nextapp.echo2.webrender.servermessage.ClientConfigurationUpdate; 53 import nextapp.echo2.webrender.servermessage.ClientPropertiesStore; 54 import nextapp.echo2.webrender.servermessage.ServerDelayMessageUpdate; 55 import nextapp.echo2.webrender.util.DomUtil; 56 57 68 public abstract class SynchronizeService 69 implements Service { 70 71 78 public static interface ClientMessagePartProcessor { 79 80 87 public String getName(); 88 89 96 public void process(UserInstance userInstance, Element messagePartElement); 97 } 98 99 102 public static final String SERVICE_ID = "Echo.Synchronize"; 103 104 107 private Map clientMessagePartProcessorMap = new HashMap (); 108 109 112 public SynchronizeService() { 113 super(); 114 registerClientMessagePartProcessor(new ClientAnalyzerProcessor()); 115 } 116 117 127 private InputStream cleanXmlInputStream(InputStream in, String characterEncoding) 128 throws IOException { 129 ByteArrayOutputStream byteOut = new ByteArrayOutputStream (); 130 131 byte[] buffer = new byte[4096]; 132 int bytesRead = 0; 133 134 try { 135 do { 136 bytesRead = in.read(buffer); 137 if (bytesRead > 0) { 138 byteOut.write(buffer, 0, bytesRead); 139 } 140 } while (bytesRead > 0); 141 } finally { 142 if (in != null) { try { in.close(); } catch (IOException ex) { } } 143 } 144 145 in.close(); 146 147 byte[] data = byteOut.toByteArray(); 148 data = new String (data, characterEncoding).trim().getBytes(characterEncoding); 149 150 return new ByteArrayInputStream (data); 151 } 152 153 156 public String getId() { 157 return SERVICE_ID; 158 } 159 160 163 public int getVersion() { 164 return DO_NOT_CACHE; 165 } 166 167 174 private Document parseRequestDocument(Connection conn) 175 throws IOException { 176 HttpServletRequest request = conn.getRequest(); 177 InputStream in = null; 178 try { 179 String userAgent = conn.getRequest().getHeader("user-agent"); 180 if (userAgent != null && userAgent.indexOf("onqueror") != -1) { 181 in = cleanXmlInputStream(request.getInputStream(), conn.getUserInstance().getCharacterEncoding()); 184 } else { 185 in = request.getInputStream(); 186 } 187 return DomUtil.getDocumentBuilder().parse(in); 188 } catch (SAXException ex) { 189 throw new IOException ("Provided InputStream cannot be parsed: " + ex); 190 } catch (IOException ex) { 191 throw new IOException ("Provided InputStream cannot be parsed: " + ex); 192 } finally { 193 if (in != null) { try { in.close(); } catch (IOException ex) { } } 194 } 195 } 196 197 207 protected void processClientMessage(Connection conn, Document clientMessageDocument) { 208 UserInstance userInstance = conn.getUserInstance(); 209 Element [] messageParts = DomUtil.getChildElementsByTagName(clientMessageDocument.getDocumentElement(), 210 "message-part"); 211 for (int i = 0; i < messageParts.length; ++i) { 212 ClientMessagePartProcessor processor = 213 (ClientMessagePartProcessor) clientMessagePartProcessorMap.get(messageParts[i].getAttribute("processor")); 214 if (processor == null) { 215 throw new RuntimeException ("Invalid processor name \"" + messageParts[i].getAttribute("processor") + "\"."); 216 } 217 processor.process(userInstance, messageParts[i]); 218 } 219 } 220 221 230 protected void registerClientMessagePartProcessor(ClientMessagePartProcessor processor) { 231 if (clientMessagePartProcessorMap.containsKey(processor.getName())) { 232 throw new IllegalStateException ("Processor already registered with name \"" + processor.getName() + "\"."); 233 } 234 clientMessagePartProcessorMap.put(processor.getName(), processor); 235 } 236 237 245 protected abstract ServerMessage renderInit(Connection conn, Document clientMessageDocument); 246 247 255 protected abstract ServerMessage renderUpdate(Connection conn, Document clientMessageDocument); 256 257 260 public void service(Connection conn) 261 throws IOException { 262 UserInstance userInstance = conn.getUserInstance(); 263 synchronized(userInstance) { 264 Document clientMessageDocument = parseRequestDocument(conn); 265 String messageType = clientMessageDocument.getDocumentElement().getAttribute("type"); 266 ServerMessage serverMessage; 267 268 if ("initialize".equals(messageType)) { 269 serverMessage = renderInit(conn, clientMessageDocument); 270 ClientPropertiesStore.renderStoreDirective(serverMessage, userInstance.getClientProperties()); 271 ClientConfigurationUpdate.renderUpdateDirective(serverMessage, userInstance.getClientConfiguration()); 272 ServerDelayMessageUpdate.renderUpdateDirective(serverMessage, userInstance.getServerDelayMessage()); 273 274 serverMessage.getDocument().getDocumentElement().setAttribute("xml-attr-test", "x&y"); 278 } else { 279 serverMessage = renderUpdate(conn, clientMessageDocument); 280 processUserInstanceUpdates(userInstance, serverMessage); 281 } 282 serverMessage.setTransactionId(userInstance.getNextTransactionId()); 283 conn.setContentType(ContentType.TEXT_XML); 284 serverMessage.render(conn.getWriter()); 285 } 286 } 287 288 294 private void processUserInstanceUpdates(UserInstance userInstance, ServerMessage serverMessage) { 295 UserInstanceUpdateManager updateManager = userInstance.getUserInstanceUpdateManager(); 296 String [] updatedPropertyNames = updateManager.getPropertyUpdateNames(); 297 for (int i = 0; i < updatedPropertyNames.length; ++i) { 298 if (UserInstance.PROPERTY_CLIENT_CONFIGURATION.equals(updatedPropertyNames[i])) { 299 ClientConfigurationUpdate.renderUpdateDirective(serverMessage, userInstance.getClientConfiguration()); 300 } else if (UserInstance.PROPERTY_SERVER_DELAY_MESSAGE.equals(updatedPropertyNames[i])) { 301 ServerDelayMessageUpdate.renderUpdateDirective(serverMessage, userInstance.getServerDelayMessage()); 302 } 303 } 304 updateManager.purge(); 305 } 306 } 307 | Popular Tags |