Initial implementation of ROP refactoring decoupling Hessian from connectivity layer and introducing pluggable serialization and connectivity layers.
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/83185f25 Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/83185f25 Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/83185f25 Branch: refs/heads/master Commit: 83185f2558f764cf60b137a2e2eeda47d366a17f Parents: f72db8b Author: Dzmitry Kazimirchyk <dkazimirc...@gmail.com> Authored: Tue Jan 19 01:38:28 2016 +0300 Committer: Dzmitry Kazimirchyk <dkazimirc...@gmail.com> Committed: Tue Mar 1 12:49:03 2016 +0300 ---------------------------------------------------------------------- .../configuration/rop/client/ClientModule.java | 9 +- .../rop/client/HessianConnectionProvider.java | 63 ----- .../apache/cayenne/remote/BaseConnection.java | 21 -- .../remote/hessian/ClientSerializerFactory.java | 2 +- .../remote/hessian/HessianConnection.java | 2 +- .../cayenne/rop/DefaultClientConnection.java | 122 ++++++++++ .../rop/DefaultClientConnectionProvider.java | 44 ++++ .../apache/cayenne/rop/ProxyRemoteService.java | 59 +++++ .../org/apache/cayenne/rop/ROPConnector.java | 32 +++ ...ientHessianSerializationServiceProvider.java | 39 ++++ .../cayenne/rop/http/HttpROPConnector.java | 233 +++++++++++++++++++ .../rop/http/HttpROPConnectorProvider.java | 58 +++++ .../rop/client/ClientModuleTest.java | 4 +- .../rop/server/ROPServerModule.java | 7 +- .../service/ServerSerializerFactory.java | 2 +- .../rop/HessianROPSerializationService.java | 69 ++++++ .../org/apache/cayenne/rop/ROPConstants.java | 28 +++ .../cayenne/rop/ROPSerializationService.java | 34 +++ .../java/org/apache/cayenne/rop/ROPServlet.java | 122 ++++++++++ ...rverHessianSerializationServiceProvider.java | 37 +++ .../cayenne/rop/ServerHttpRemoteService.java | 48 ++++ 21 files changed, 943 insertions(+), 92 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/ClientModule.java ---------------------------------------------------------------------- diff --git a/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/ClientModule.java b/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/ClientModule.java index de64f08..041408a 100644 --- a/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/ClientModule.java +++ b/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/ClientModule.java @@ -32,6 +32,10 @@ import org.apache.cayenne.di.Module; import org.apache.cayenne.event.DefaultEventManager; import org.apache.cayenne.event.EventManager; import org.apache.cayenne.remote.ClientConnection; +import org.apache.cayenne.remote.RemoteService; +import org.apache.cayenne.rop.*; +import org.apache.cayenne.rop.http.ClientHessianSerializationServiceProvider; +import org.apache.cayenne.rop.http.HttpROPConnectorProvider; /** * A DI module containing all Cayenne ROP client runtime configurations. @@ -56,7 +60,10 @@ public class ClientModule implements Module { binder.<String> bindMap(Constants.PROPERTIES_MAP).putAll(properties); binder.bind(ObjectContextFactory.class).to(CayenneContextFactory.class); - binder.bind(ClientConnection.class).toProvider(HessianConnectionProvider.class); + binder.bind(ROPSerializationService.class).toProvider(ClientHessianSerializationServiceProvider.class); + binder.bind(ROPConnector.class).toProvider(HttpROPConnectorProvider.class); + binder.bind(RemoteService.class).to(ProxyRemoteService.class); + binder.bind(ClientConnection.class).toProvider(DefaultClientConnectionProvider.class); binder.bind(EventManager.class).to(DefaultEventManager.class); binder.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class); binder.bind(DataChannel.class).toProvider(ClientChannelProvider.class); http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/HessianConnectionProvider.java ---------------------------------------------------------------------- diff --git a/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/HessianConnectionProvider.java b/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/HessianConnectionProvider.java deleted file mode 100644 index 21fda18..0000000 --- a/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/HessianConnectionProvider.java +++ /dev/null @@ -1,63 +0,0 @@ -/***************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - ****************************************************************/ -package org.apache.cayenne.configuration.rop.client; - -import org.apache.cayenne.ConfigurationException; -import org.apache.cayenne.configuration.Constants; -import org.apache.cayenne.configuration.RuntimeProperties; -import org.apache.cayenne.di.Inject; -import org.apache.cayenne.di.Provider; -import org.apache.cayenne.remote.ClientConnection; -import org.apache.cayenne.remote.hessian.HessianConnection; - -public class HessianConnectionProvider implements Provider<ClientConnection> { - - @Inject - protected RuntimeProperties runtimeProperties; - - public ClientConnection get() throws ConfigurationException { - - String url = runtimeProperties.get(Constants.ROP_SERVICE_URL_PROPERTY); - if (url == null) { - throw new ConfigurationException( - "No property defined for '%s', can't initialize HessianConnection", - Constants.ROP_SERVICE_URL_PROPERTY); - } - - String userName = runtimeProperties.get(Constants.ROP_SERVICE_USERNAME_PROPERTY); - String password = runtimeProperties.get(Constants.ROP_SERVICE_PASSWORD_PROPERTY); - String sharedSession = runtimeProperties - .get(Constants.ROP_SERVICE_SHARED_SESSION_PROPERTY); - long readTimeout = runtimeProperties.getLong( - Constants.ROP_SERVICE_TIMEOUT_PROPERTY, - -1l); - - HessianConnection result = new HessianConnection( - url, - userName, - password, - sharedSession); - - if (readTimeout > 0) { - result.setReadTimeout(readTimeout); - } - - return result; - } -} http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/main/java/org/apache/cayenne/remote/BaseConnection.java ---------------------------------------------------------------------- diff --git a/cayenne-client/src/main/java/org/apache/cayenne/remote/BaseConnection.java b/cayenne-client/src/main/java/org/apache/cayenne/remote/BaseConnection.java index 74dd3f4..d02449e 100644 --- a/cayenne-client/src/main/java/org/apache/cayenne/remote/BaseConnection.java +++ b/cayenne-client/src/main/java/org/apache/cayenne/remote/BaseConnection.java @@ -33,7 +33,6 @@ public abstract class BaseConnection implements ClientConnection { protected Log logger; protected long messageId; - protected long readTimeout = 0L; /** * Default constructor that initializes logging and a single threaded EventManager. @@ -111,26 +110,6 @@ public abstract class BaseConnection implements ClientConnection { public long getProcessedMessagesCount() { return messageId + 1; } - - /** - * The socket timeout on requests in milliseconds. Defaults to infinity. - * - * @since 3.1 - */ - public long getReadTimeout() { - return readTimeout; - } - - /** - * Sets the socket timeout. - * - * @param readTimeout The socket timeout on requests in milliseconds. - * - * @since 3.1 - */ - public void setReadTimeout(long readTimeout) { - this.readTimeout = readTimeout; - } /** * Called before logging the beginning of message processing. http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/ClientSerializerFactory.java ---------------------------------------------------------------------- diff --git a/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/ClientSerializerFactory.java b/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/ClientSerializerFactory.java index f39d642..ff7aeb3 100644 --- a/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/ClientSerializerFactory.java +++ b/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/ClientSerializerFactory.java @@ -34,7 +34,7 @@ import com.caucho.hessian.io.Serializer; * * @since 1.2 */ -class ClientSerializerFactory extends AbstractSerializerFactory { +public class ClientSerializerFactory extends AbstractSerializerFactory { private Deserializer dataRowDeserializer; private Deserializer listDeserializer; http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/HessianConnection.java ---------------------------------------------------------------------- diff --git a/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/HessianConnection.java b/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/HessianConnection.java index d8f6ee2..3bea90d 100644 --- a/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/HessianConnection.java +++ b/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/HessianConnection.java @@ -226,7 +226,7 @@ public class HessianConnection extends BaseConnection { factory.setConnectionFactory(new HessianURLConnectionFactory(this)); factory.setUser(userName); factory.setPassword(password); - factory.setReadTimeout(getReadTimeout()); +// factory.setReadTimeout(getReadTimeout()); this.serializerFactory = factory.getSerializerFactory(); http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnection.java ---------------------------------------------------------------------- diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnection.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnection.java new file mode 100644 index 0000000..2004c6e --- /dev/null +++ b/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnection.java @@ -0,0 +1,122 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.rop; + +import org.apache.cayenne.CayenneRuntimeException; +import org.apache.cayenne.event.EventBridge; +import org.apache.cayenne.event.EventBridgeFactory; +import org.apache.cayenne.remote.BaseConnection; +import org.apache.cayenne.remote.ClientMessage; +import org.apache.cayenne.remote.RemoteService; +import org.apache.cayenne.remote.RemoteSession; + +public class DefaultClientConnection extends BaseConnection { + + private RemoteService remoteService; + private RemoteSession session; + + private String sharedSessionName; + + public DefaultClientConnection(RemoteService remoteService, String sharedSession) { + this.remoteService = remoteService; + this.sharedSessionName = sharedSession; + } + + @Override + protected void beforeSendMessage(ClientMessage message) throws CayenneRuntimeException { + if (session == null) { + connect(); + } + } + + @Override + protected Object doSendMessage(ClientMessage message) throws CayenneRuntimeException { + try { + return remoteService.processMessage(message); + } + catch (CayenneRuntimeException e) { + throw e; + } + catch (Throwable th) { + throw new CayenneRuntimeException(th.getMessage(), th); + } + } + + @Override + public EventBridge getServerEventBridge() throws CayenneRuntimeException { + if (session == null) { + connect(); + } + + return createServerEventBridge(session); + } + + protected synchronized void connect() { + if (session != null) { + return; + } + + long t0 = System.currentTimeMillis(); + + // create server session... + try { + this.session = (sharedSessionName != null) ? remoteService + .establishSharedSession(sharedSessionName) : remoteService + .establishSession(); + } + catch (Throwable th) { + logger.info(th.getMessage(), th); + throw new CayenneRuntimeException(th.getMessage(), th); + } + + if (logger.isInfoEnabled()) { + long time = System.currentTimeMillis() - t0; + logger.info("=== Connected, session: " + + session + + " - took " + + time + + " ms."); + } + } + + /** + * Creates an EventBridge that will listen for server events. Returns null if server + * events support is not configured in the descriptor. + * + * @throws CayenneRuntimeException if EventBridge startup fails for any reason. + */ + protected EventBridge createServerEventBridge(RemoteSession session) throws CayenneRuntimeException { + + if (!session.isServerEventsEnabled()) { + return null; + } + + try { + EventBridgeFactory factory = (EventBridgeFactory) Class.forName(session.getEventBridgeFactory()) + .newInstance(); + + // must use "name", not the sessionId as an external subject for the + // event bridge + return factory.createEventBridge(RemoteSession.getSubjects(), session.getName(), + session.getEventBridgeParameters()); + } catch (Exception ex) { + throw new CayenneRuntimeException("Error creating EventBridge.", ex); + } + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnectionProvider.java ---------------------------------------------------------------------- diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnectionProvider.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnectionProvider.java new file mode 100644 index 0000000..a6dc9e5 --- /dev/null +++ b/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnectionProvider.java @@ -0,0 +1,44 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.rop; + +import org.apache.cayenne.configuration.Constants; +import org.apache.cayenne.configuration.RuntimeProperties; +import org.apache.cayenne.di.DIRuntimeException; +import org.apache.cayenne.di.Inject; +import org.apache.cayenne.di.Provider; +import org.apache.cayenne.remote.ClientConnection; +import org.apache.cayenne.remote.RemoteService; + +public class DefaultClientConnectionProvider implements Provider<ClientConnection> { + + @Inject + protected RuntimeProperties runtimeProperties; + + @Inject + protected RemoteService remoteService; + + @Override + public ClientConnection get() throws DIRuntimeException { + String sharedSession = runtimeProperties + .get(Constants.ROP_SERVICE_SHARED_SESSION_PROPERTY); + + return new DefaultClientConnection(remoteService, sharedSession); + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/main/java/org/apache/cayenne/rop/ProxyRemoteService.java ---------------------------------------------------------------------- diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/ProxyRemoteService.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/ProxyRemoteService.java new file mode 100644 index 0000000..ecfb441 --- /dev/null +++ b/cayenne-client/src/main/java/org/apache/cayenne/rop/ProxyRemoteService.java @@ -0,0 +1,59 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.rop; + +import org.apache.cayenne.di.Inject; +import org.apache.cayenne.remote.ClientMessage; +import org.apache.cayenne.remote.RemoteService; +import org.apache.cayenne.remote.RemoteSession; + +import java.io.IOException; +import java.rmi.RemoteException; + +public class ProxyRemoteService implements RemoteService { + + @Inject + protected ROPSerializationService serializationService; + + @Inject + protected ROPConnector ropConnector; + + @Override + public RemoteSession establishSession() throws RemoteException { + try { + return serializationService.deserialize(ropConnector.establishSession(), RemoteSession.class); + } catch (IOException e) { + throw new RemoteException(e.getMessage()); + } + } + + @Override + public RemoteSession establishSharedSession(String name) throws RemoteException { + try { + return serializationService.deserialize(ropConnector.establishSharedSession(name), RemoteSession.class); + } catch (IOException e) { + throw new RemoteException(e.getMessage()); + } + } + + @Override + public Object processMessage(ClientMessage message) throws RemoteException, Throwable { + return serializationService.deserialize(ropConnector.sendMessage(serializationService.serialize(message)), Object.class); + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/main/java/org/apache/cayenne/rop/ROPConnector.java ---------------------------------------------------------------------- diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/ROPConnector.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/ROPConnector.java new file mode 100644 index 0000000..4976d80 --- /dev/null +++ b/cayenne-client/src/main/java/org/apache/cayenne/rop/ROPConnector.java @@ -0,0 +1,32 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.rop; + +import java.io.IOException; +import java.io.InputStream; + +public interface ROPConnector { + + InputStream establishSession() throws IOException; + + InputStream establishSharedSession(String name) throws IOException; + + InputStream sendMessage(byte[] message) throws IOException; + +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/main/java/org/apache/cayenne/rop/http/ClientHessianSerializationServiceProvider.java ---------------------------------------------------------------------- diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/http/ClientHessianSerializationServiceProvider.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/http/ClientHessianSerializationServiceProvider.java new file mode 100644 index 0000000..ecf9339 --- /dev/null +++ b/cayenne-client/src/main/java/org/apache/cayenne/rop/http/ClientHessianSerializationServiceProvider.java @@ -0,0 +1,39 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.rop.http; + +import org.apache.cayenne.di.DIRuntimeException; +import org.apache.cayenne.di.Provider; +import org.apache.cayenne.remote.hessian.ClientSerializerFactory; +import org.apache.cayenne.remote.hessian.HessianConfig; +import org.apache.cayenne.rop.HessianROPSerializationService; +import org.apache.cayenne.rop.ROPSerializationService; + +public class ClientHessianSerializationServiceProvider implements Provider<ROPSerializationService> { + + public static final String[] CLIENT_SERIALIZER_FACTORIES = new String[] { + ClientSerializerFactory.class.getName() + }; + + @Override + public ROPSerializationService get() throws DIRuntimeException { + return new HessianROPSerializationService( + HessianConfig.createFactory(CLIENT_SERIALIZER_FACTORIES, null)); + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnector.java ---------------------------------------------------------------------- diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnector.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnector.java new file mode 100644 index 0000000..786add2 --- /dev/null +++ b/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnector.java @@ -0,0 +1,233 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.rop.http; + +import org.apache.cayenne.rop.ROPConnector; +import org.apache.cayenne.rop.ROPConstants; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.net.URLConnection; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +public class HttpROPConnector implements ROPConnector { + + private static Log logger = LogFactory.getLog(HttpROPConnector.class); + + private String url; + + private String username; + private String password; + + private Long readTimeout; + + public HttpROPConnector(String url, String username, String password) { + this.url = url; + this.username = username; + this.password = password; + } + + public void setReadTimeout(Long readTimeout) { + this.readTimeout = readTimeout; + } + + @Override + public InputStream establishSession() throws IOException { + if (logger.isInfoEnabled()) { + logConnect(null); + } + + Map<String, String> requestParams = new HashMap<>(); + requestParams.put(ROPConstants.OPERATION_PARAMETER, ROPConstants.ESTABLISH_SESSION_OPERATION); + + return doRequest(requestParams); + } + + @Override + public InputStream establishSharedSession(String name) throws IOException { + if (logger.isInfoEnabled()) { + logConnect(name); + } + + Map<String, String> requestParams = new HashMap<>(); + requestParams.put(ROPConstants.OPERATION_PARAMETER, ROPConstants.ESTABLISH_SHARED_SESSION_OPERATION); + requestParams.put(ROPConstants.SESSION_NAME_PARAMETER, name); + + return doRequest(requestParams); + } + + @Override + public InputStream sendMessage(byte[] message) throws IOException { + return doRequest(message); + } + + protected InputStream doRequest(Map<String, String> params) throws IOException { + URLConnection connection = new URL(url).openConnection(); + + StringBuilder urlParams = new StringBuilder(); + + for (Map.Entry<String, String> entry : params.entrySet()) { + if (urlParams.length() > 0) { + urlParams.append('&'); + } + + urlParams.append(entry.getKey()); + urlParams.append('='); + urlParams.append(entry.getValue()); + } + + if (readTimeout != null) { + connection.setReadTimeout(readTimeout.intValue()); + } + + addAuthHeader(connection); + + connection.setDoOutput(true); + + connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + connection.setRequestProperty("charset", "utf-8"); + + try (OutputStream output = connection.getOutputStream()) { + output.write(urlParams.toString().getBytes(StandardCharsets.UTF_8)); + } + + return connection.getInputStream(); + } + + protected InputStream doRequest(byte[] data) throws IOException { + URLConnection connection = new URL(url).openConnection(); + + if (readTimeout != null) { + connection.setReadTimeout(readTimeout.intValue()); + } + + addAuthHeader(connection); + connection.setDoOutput(true); + + if (data != null) { + try (OutputStream output = connection.getOutputStream()) { + output.write(data); + } + } + + return connection.getInputStream(); + } + + protected void addAuthHeader(URLConnection connection) { + String basicAuth = getBasicAuth(username, password); + + if (basicAuth != null) { + connection.addRequestProperty("Authorization", basicAuth); + } + } + + public String getBasicAuth(String user, String password) { + if (user != null && password != null) { + return "Basic " + base64(user + ":" + password); + } + + return null; + } + + /** + * Creates the Base64 value. + */ + private String base64(String value) { + StringBuffer cb = new StringBuffer(); + + int i = 0; + for (i = 0; i + 2 < value.length(); i += 3) { + long chunk = (int) value.charAt(i); + chunk = (chunk << 8) + (int) value.charAt(i + 1); + chunk = (chunk << 8) + (int) value.charAt(i + 2); + + cb.append(encode(chunk >> 18)); + cb.append(encode(chunk >> 12)); + cb.append(encode(chunk >> 6)); + cb.append(encode(chunk)); + } + + if (i + 1 < value.length()) { + long chunk = (int) value.charAt(i); + chunk = (chunk << 8) + (int) value.charAt(i + 1); + chunk <<= 8; + + cb.append(encode(chunk >> 18)); + cb.append(encode(chunk >> 12)); + cb.append(encode(chunk >> 6)); + cb.append('='); + } + else if (i < value.length()) { + long chunk = (int) value.charAt(i); + chunk <<= 16; + + cb.append(encode(chunk >> 18)); + cb.append(encode(chunk >> 12)); + cb.append('='); + cb.append('='); + } + + return cb.toString(); + } + + public static char encode(long d) { + d &= 0x3f; + if (d < 26) + return (char) (d + 'A'); + else if (d < 52) + return (char) (d + 'a' - 26); + else if (d < 62) + return (char) (d + '0' - 52); + else if (d == 62) + return '+'; + else + return '/'; + } + + private void logConnect(String sharedSessionName) { + StringBuilder log = new StringBuilder("Connecting to ["); + if (username != null) { + log.append(username); + + if (password != null) { + log.append(":*******"); + } + + log.append("@"); + } + + log.append(url); + log.append("]"); + + if (sharedSessionName != null) { + log.append(" - shared session '").append(sharedSessionName).append("'"); + } + else { + log.append(" - dedicated session."); + } + + logger.info(log.toString()); + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnectorProvider.java ---------------------------------------------------------------------- diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnectorProvider.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnectorProvider.java new file mode 100644 index 0000000..919a51f --- /dev/null +++ b/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnectorProvider.java @@ -0,0 +1,58 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.rop.http; + +import org.apache.cayenne.ConfigurationException; +import org.apache.cayenne.configuration.Constants; +import org.apache.cayenne.configuration.RuntimeProperties; +import org.apache.cayenne.di.DIRuntimeException; +import org.apache.cayenne.di.Inject; +import org.apache.cayenne.di.Provider; +import org.apache.cayenne.rop.ROPConnector; + +public class HttpROPConnectorProvider implements Provider<ROPConnector> { + + @Inject + protected RuntimeProperties runtimeProperties; + + @Override + public ROPConnector get() throws DIRuntimeException { + String url = runtimeProperties.get(Constants.ROP_SERVICE_URL_PROPERTY); + if (url == null) { + throw new ConfigurationException( + "No property defined for '%s', can't initialize HessianConnection", + Constants.ROP_SERVICE_URL_PROPERTY); + } + + String userName = runtimeProperties.get(Constants.ROP_SERVICE_USERNAME_PROPERTY); + String password = runtimeProperties.get(Constants.ROP_SERVICE_PASSWORD_PROPERTY); + + long readTimeout = runtimeProperties.getLong( + Constants.ROP_SERVICE_TIMEOUT_PROPERTY, + -1L); + + HttpROPConnector result = new HttpROPConnector(url, userName, password); + + if (readTimeout > 0) { + result.setReadTimeout(readTimeout); + } + + return result; + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/test/java/org/apache/cayenne/configuration/rop/client/ClientModuleTest.java ---------------------------------------------------------------------- diff --git a/cayenne-client/src/test/java/org/apache/cayenne/configuration/rop/client/ClientModuleTest.java b/cayenne-client/src/test/java/org/apache/cayenne/configuration/rop/client/ClientModuleTest.java index 03d0ad6..836507b 100644 --- a/cayenne-client/src/test/java/org/apache/cayenne/configuration/rop/client/ClientModuleTest.java +++ b/cayenne-client/src/test/java/org/apache/cayenne/configuration/rop/client/ClientModuleTest.java @@ -28,7 +28,7 @@ import org.apache.cayenne.event.DefaultEventManager; import org.apache.cayenne.remote.ClientChannel; import org.apache.cayenne.remote.ClientConnection; import org.apache.cayenne.remote.MockClientConnection; -import org.apache.cayenne.remote.hessian.HessianConnection; +import org.apache.cayenne.rop.DefaultClientConnection; import org.junit.Test; import java.util.HashMap; @@ -52,7 +52,7 @@ public class ClientModuleTest { ClientConnection connection = injector.getInstance(ClientConnection.class); assertNotNull(connection); - assertTrue(connection instanceof HessianConnection); + assertTrue(connection instanceof DefaultClientConnection); assertSame("Connection must be a singleton", connection, injector .getInstance(ClientConnection.class)); http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-server/src/main/java/org/apache/cayenne/configuration/rop/server/ROPServerModule.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/rop/server/ROPServerModule.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/rop/server/ROPServerModule.java index 6c9a7ea..ceefd62 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/rop/server/ROPServerModule.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/rop/server/ROPServerModule.java @@ -25,7 +25,9 @@ import org.apache.cayenne.di.Binder; import org.apache.cayenne.di.MapBuilder; import org.apache.cayenne.di.Module; import org.apache.cayenne.remote.RemoteService; -import org.apache.cayenne.remote.hessian.service.HessianService; +import org.apache.cayenne.rop.ServerHessianSerializationServiceProvider; +import org.apache.cayenne.rop.ServerHttpRemoteService; +import org.apache.cayenne.rop.ROPSerializationService; /** * A DI module that defines services for the server-side of an ROP application based on @@ -47,7 +49,8 @@ public class ROPServerModule implements Module { .bindMap(Constants.SERVER_ROP_EVENT_BRIDGE_PROPERTIES_MAP); mapBuilder.putAll(eventBridgeProperties); - binder.bind(RemoteService.class).to(HessianService.class); + binder.bind(RemoteService.class).to(ServerHttpRemoteService.class); + binder.bind(ROPSerializationService.class).toProvider(ServerHessianSerializationServiceProvider.class); } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-server/src/main/java/org/apache/cayenne/remote/hessian/service/ServerSerializerFactory.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/remote/hessian/service/ServerSerializerFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/remote/hessian/service/ServerSerializerFactory.java index 3097e36e..3310cee 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/remote/hessian/service/ServerSerializerFactory.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/remote/hessian/service/ServerSerializerFactory.java @@ -34,7 +34,7 @@ import com.caucho.hessian.io.Serializer; * * @since 1.2 */ -class ServerSerializerFactory extends AbstractSerializerFactory { +public class ServerSerializerFactory extends AbstractSerializerFactory { private ServerPersistentObjectListSerializer persistentObjectListSerializer; private ServerDataRowSerializer dataRowSerilaizer; private Serializer javaSerializer; http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-server/src/main/java/org/apache/cayenne/rop/HessianROPSerializationService.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/rop/HessianROPSerializationService.java b/cayenne-server/src/main/java/org/apache/cayenne/rop/HessianROPSerializationService.java new file mode 100644 index 0000000..5b0c9a0 --- /dev/null +++ b/cayenne-server/src/main/java/org/apache/cayenne/rop/HessianROPSerializationService.java @@ -0,0 +1,69 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.rop; + +import com.caucho.hessian.io.Hessian2Output; +import com.caucho.hessian.io.HessianInput; +import com.caucho.hessian.io.HessianOutput; +import com.caucho.hessian.io.SerializerFactory; +import org.apache.cayenne.DataChannel; +import org.apache.cayenne.di.Inject; +import org.apache.cayenne.remote.hessian.HessianConfig; +import org.apache.cayenne.remote.hessian.service.HessianService; + +import java.io.*; + +public class HessianROPSerializationService implements ROPSerializationService { + + protected SerializerFactory serializerFactory; + + public HessianROPSerializationService(SerializerFactory serializerFactory) { + this.serializerFactory = serializerFactory; + } + + @Override + public byte[] serialize(Object object) throws IOException { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + HessianOutput out = new HessianOutput(bytes); + out.setSerializerFactory(serializerFactory); + out.writeObject(object); + + return bytes.toByteArray(); + } + + @Override + public void serialize(Object object, OutputStream outputStream) throws IOException { + Hessian2Output out = new Hessian2Output(outputStream); + out.setSerializerFactory(serializerFactory); + out.writeObject(object); + } + + @Override + public <T> T deserialize(byte[] serializedObject, Class<T> objectClass) { + return null; + } + + @Override + public <T> T deserialize(InputStream input, Class<T> objectClass) throws IOException { + HessianInput in = new HessianInput(input); + in.setSerializerFactory(serializerFactory); + + return objectClass.cast(in.readObject()); + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPConstants.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPConstants.java b/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPConstants.java new file mode 100644 index 0000000..e076eee --- /dev/null +++ b/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPConstants.java @@ -0,0 +1,28 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.rop; + +public class ROPConstants { + + public static final String OPERATION_PARAMETER = "operation"; + public static final String SESSION_NAME_PARAMETER = "session_name"; + + public static final String ESTABLISH_SESSION_OPERATION = "establish_session"; + public static final String ESTABLISH_SHARED_SESSION_OPERATION = "establish_shared_session"; +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPSerializationService.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPSerializationService.java b/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPSerializationService.java new file mode 100644 index 0000000..18c8cdb --- /dev/null +++ b/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPSerializationService.java @@ -0,0 +1,34 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.rop; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public interface ROPSerializationService { + + byte[] serialize(Object object) throws IOException; + + void serialize(Object object, OutputStream outputStream) throws IOException; + + <T> T deserialize(InputStream inputStream, Class<T> objectClass) throws IOException; + + <T> T deserialize(byte[] serializedObject, Class<T> objectClass) throws IOException; +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPServlet.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPServlet.java b/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPServlet.java new file mode 100644 index 0000000..db8d5fb --- /dev/null +++ b/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPServlet.java @@ -0,0 +1,122 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.rop; + +import org.apache.cayenne.configuration.CayenneRuntime; +import org.apache.cayenne.configuration.rop.server.ROPServerModule; +import org.apache.cayenne.configuration.server.ServerRuntime; +import org.apache.cayenne.configuration.web.WebConfiguration; +import org.apache.cayenne.configuration.web.WebUtil; +import org.apache.cayenne.di.Module; +import org.apache.cayenne.remote.ClientMessage; +import org.apache.cayenne.remote.RemoteService; +import org.apache.cayenne.remote.RemoteSession; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Collection; +import java.util.Map; + +public class ROPServlet extends HttpServlet { + + protected ServletContext servletContext; + protected RemoteService remoteService; + protected ROPSerializationService serializationService; + + @Override + public void init(ServletConfig configuration) throws ServletException { + + checkAlreadyConfigured(configuration.getServletContext()); + + this.servletContext = configuration.getServletContext(); + + WebConfiguration configAdapter = new WebConfiguration(configuration); + + String configurationLocation = configAdapter.getConfigurationLocation(); + Map<String, String> eventBridgeParameters = configAdapter.getOtherParameters(); + + Collection<Module> modules = configAdapter.createModules(new ROPServerModule( + eventBridgeParameters)); + + ServerRuntime runtime = new ServerRuntime(configurationLocation, modules + .toArray(new Module[modules.size()])); + + this.remoteService = runtime.getInjector().getInstance(RemoteService.class); + this.serializationService = runtime.getInjector().getInstance(ROPSerializationService.class); + + WebUtil.setCayenneRuntime(servletContext, runtime); + super.init(configuration); + } + + protected void checkAlreadyConfigured(ServletContext context) throws ServletException { + // sanity check + if (WebUtil.getCayenneRuntime(context) != null) { + throw new ServletException( + "CayenneRuntime is already configured in the servlet environment"); + } + } + + @Override + public void destroy() { + super.destroy(); + + CayenneRuntime runtime = WebUtil.getCayenneRuntime(servletContext); + if (runtime != null) { + runtime.shutdown(); + } + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + try { + String operation = req.getParameter(ROPConstants.OPERATION_PARAMETER); + + if (operation != null) { + switch (operation) { + case ROPConstants.ESTABLISH_SESSION_OPERATION: + RemoteSession session = remoteService.establishSession(); + serializationService.serialize(session, resp.getOutputStream()); + break; + case ROPConstants.ESTABLISH_SHARED_SESSION_OPERATION: + String sessionName = req.getParameter(ROPConstants.SESSION_NAME_PARAMETER); + RemoteSession sharedSession = remoteService.establishSharedSession(sessionName); + + serializationService.serialize(sharedSession, resp.getOutputStream()); + break; + default: + throw new ServletException("Unknown operation: " + operation); + } + } else { + Object response = remoteService.processMessage( + serializationService.deserialize(req.getInputStream(), ClientMessage.class)); + + serializationService.serialize(response, resp.getOutputStream()); + } + } catch (RuntimeException | ServletException e) { + throw e; + } catch (Throwable e) { + throw new ServletException(e); + } + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-server/src/main/java/org/apache/cayenne/rop/ServerHessianSerializationServiceProvider.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/rop/ServerHessianSerializationServiceProvider.java b/cayenne-server/src/main/java/org/apache/cayenne/rop/ServerHessianSerializationServiceProvider.java new file mode 100644 index 0000000..ec0c21c --- /dev/null +++ b/cayenne-server/src/main/java/org/apache/cayenne/rop/ServerHessianSerializationServiceProvider.java @@ -0,0 +1,37 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.rop; + +import org.apache.cayenne.di.DIRuntimeException; +import org.apache.cayenne.di.Provider; +import org.apache.cayenne.remote.hessian.HessianConfig; +import org.apache.cayenne.remote.hessian.service.ServerSerializerFactory; + +public class ServerHessianSerializationServiceProvider implements Provider<ROPSerializationService> { + + public static final String[] SERVER_SERIALIZER_FACTORIES = new String[] { + ServerSerializerFactory.class.getName() + }; + + @Override + public ROPSerializationService get() throws DIRuntimeException { + return new HessianROPSerializationService( + HessianConfig.createFactory(SERVER_SERIALIZER_FACTORIES, null)); + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-server/src/main/java/org/apache/cayenne/rop/ServerHttpRemoteService.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/rop/ServerHttpRemoteService.java b/cayenne-server/src/main/java/org/apache/cayenne/rop/ServerHttpRemoteService.java new file mode 100644 index 0000000..22aba9f --- /dev/null +++ b/cayenne-server/src/main/java/org/apache/cayenne/rop/ServerHttpRemoteService.java @@ -0,0 +1,48 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.rop; + +import com.caucho.services.server.ServiceContext; +import org.apache.cayenne.configuration.Constants; +import org.apache.cayenne.configuration.ObjectContextFactory; +import org.apache.cayenne.di.Inject; +import org.apache.cayenne.remote.service.HttpRemoteService; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import java.util.Map; + +public class ServerHttpRemoteService extends HttpRemoteService { + + public ServerHttpRemoteService(@Inject ObjectContextFactory contextFactory, + @Inject(Constants.SERVER_ROP_EVENT_BRIDGE_PROPERTIES_MAP) Map<String, String> eventBridgeProperties) { + super(contextFactory, eventBridgeProperties); + } + + @Override + protected HttpSession getSession(boolean create) { + HttpServletRequest request = (HttpServletRequest) ServiceContext.getContextRequest(); + if (request == null) { + throw new IllegalStateException( + "Attempt to access HttpSession outside the request scope."); + } + + return request.getSession(create); + } +}