001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.camel.component.javaspace;
018
019 import java.io.ByteArrayInputStream;
020 import java.io.ByteArrayOutputStream;
021 import java.io.File;
022 import java.io.ObjectInputStream;
023 import java.io.ObjectOutputStream;
024 import java.rmi.RemoteException;
025 import java.util.concurrent.ScheduledThreadPoolExecutor;
026 import java.util.concurrent.TimeUnit;
027
028 import net.jini.core.entry.Entry;
029 import net.jini.core.lease.Lease;
030 import net.jini.core.transaction.CannotAbortException;
031 import net.jini.core.transaction.CannotCommitException;
032 import net.jini.core.transaction.Transaction;
033 import net.jini.core.transaction.UnknownTransactionException;
034 import net.jini.space.JavaSpace;
035
036 import org.apache.camel.ExchangePattern;
037 import org.apache.camel.Message;
038 import org.apache.camel.Processor;
039 import org.apache.camel.RuntimeCamelException;
040 import org.apache.camel.impl.DefaultConsumer;
041 import org.apache.camel.impl.DefaultExchange;
042 import org.apache.camel.util.ExchangeHelper;
043 import org.apache.commons.logging.Log;
044 import org.apache.commons.logging.LogFactory;
045
046 /**
047 * @{link Consumer} implementation for Javaspaces
048 *
049 * @version $Revision: 15488 $
050 */
051 public class JavaSpaceConsumer extends DefaultConsumer {
052
053 public static final int READ = 1;
054 public static final int TAKE = 0;
055
056 @SuppressWarnings("unused")
057 private static final transient Log LOG = LogFactory.getLog(JavaSpaceConsumer.class);
058
059 private final int concurrentConsumers;
060 private final boolean transactional;
061 private final long transactionTimeout;
062 private final String verb;
063 private final String templateId;
064 private final ScheduledThreadPoolExecutor executor;
065 private JavaSpace javaSpace;
066 private TransactionHelper transactionHelper;
067
068 public JavaSpaceConsumer(final JavaSpaceEndpoint endpoint, Processor processor) throws Exception {
069 super(endpoint, processor);
070 this.concurrentConsumers = endpoint.getConcurrentConsumers();
071 this.transactional = endpoint.isTransactional();
072 this.transactionTimeout = endpoint.getTransactionTimeout();
073 this.verb = endpoint.getVerb();
074 this.templateId = endpoint.getTemplateId();
075 this.executor = new ScheduledThreadPoolExecutor(this.concurrentConsumers);
076 }
077
078 protected void doStart() throws Exception {
079 // TODO: There should be a switch to enable/disable using this security hack
080 Utility.setSecurityPolicy("policy.all", "policy_consumer.all");
081
082 int verb = TAKE;
083 if (this.verb.equalsIgnoreCase("read")) {
084 verb = READ;
085 }
086 javaSpace = JiniSpaceAccessor.findSpace(((JavaSpaceEndpoint) this.getEndpoint()).getRemaining(),
087 ((JavaSpaceEndpoint) this.getEndpoint()).getSpaceName());
088 if (transactional) {
089 transactionHelper = TransactionHelper.getInstance(((JavaSpaceEndpoint) this.getEndpoint()).getRemaining());
090 }
091 for (int i = 0; i < concurrentConsumers; ++i) {
092 Task worker = new Task((JavaSpaceEndpoint) this.getEndpoint(), this.getProcessor(), javaSpace,
093 transactionHelper, transactionTimeout, verb, templateId);
094 executor.scheduleWithFixedDelay(worker, 0, 1, TimeUnit.NANOSECONDS);
095 }
096
097 (new File("policy_consumer.all")).delete();
098 }
099
100 @Override
101 protected void doStop() throws Exception {
102 executor.shutdown();
103 }
104
105 }
106
107 class Task implements Runnable {
108
109 private final JavaSpaceEndpoint endpoint;
110 private final Processor processor;
111 private final JavaSpace javaSpace;
112 private final TransactionHelper transactionHelper;
113 private final long transactionTimeout;
114 private final int verb;
115 private final Entry template;
116
117 public Task(JavaSpaceEndpoint endpoint, Processor processor, JavaSpace javaSpace,
118 TransactionHelper transactionHelper, long transactionTimeout, int verb, String templateId) throws Exception {
119 this.endpoint = endpoint;
120 this.processor = processor;
121 this.javaSpace = javaSpace;
122 this.transactionHelper = transactionHelper;
123 this.transactionTimeout = transactionTimeout;
124 this.verb = verb;
125 if (templateId != null) {
126 Entry tmpl = (Entry) this.endpoint.getCamelContext().getRegistry().lookup(templateId);
127 template = javaSpace.snapshot(tmpl);
128 } else {
129 this.template = javaSpace.snapshot(new InEntry());
130 }
131 }
132
133 public void run() {
134 Transaction tnx = null;
135 try {
136 DefaultExchange exchange = (DefaultExchange) endpoint.createExchange(ExchangePattern.InOut);
137 Message message = exchange.getIn();
138 if (transactionHelper != null) {
139 tnx = transactionHelper.getJiniTransaction(transactionTimeout).transaction;
140 }
141 Entry entry = null;
142 switch (verb) {
143 case JavaSpaceConsumer.TAKE:
144 entry = javaSpace.take(template, tnx, 100);
145 break;
146 case JavaSpaceConsumer.READ:
147 entry = javaSpace.read(template, tnx, 100);
148 break;
149 default:
150 throw new RuntimeCamelException("Wrong verb");
151 }
152 if (entry != null) {
153 if (entry instanceof InEntry) {
154 if (((InEntry) entry).binary) {
155 message.setBody(((InEntry) entry).buffer);
156 } else {
157 ByteArrayInputStream bis = new ByteArrayInputStream(((InEntry) entry).buffer);
158 ObjectInputStream ois = new ObjectInputStream(bis);
159 Object obj = ois.readObject();
160 message.setBody(obj);
161 }
162 processor.process(exchange);
163 Message out = exchange.getOut();
164 if (out.getBody() != null && ExchangeHelper.isOutCapable(exchange)) {
165 OutEntry replyCamelEntry = new OutEntry();
166 replyCamelEntry.correlationId = ((InEntry) entry).correlationId;
167 if (out.getBody() instanceof byte[]) {
168 replyCamelEntry.binary = true;
169 replyCamelEntry.buffer = (byte[]) out.getBody();
170 } else {
171 ByteArrayOutputStream bos = new ByteArrayOutputStream();
172 ObjectOutputStream oos = new ObjectOutputStream(bos);
173 oos.writeObject(out.getBody());
174 replyCamelEntry.binary = false;
175 replyCamelEntry.buffer = bos.toByteArray();
176 }
177 javaSpace.write(replyCamelEntry, tnx, Lease.FOREVER);
178 }
179 } else {
180 message.setBody(entry, Entry.class);
181 processor.process(exchange);
182 }
183 }
184
185 } catch (Exception e) {
186 if (tnx != null) {
187 try {
188 tnx.abort();
189 } catch (UnknownTransactionException e1) {
190 throw new RuntimeCamelException(e1);
191 } catch (CannotAbortException e1) {
192 throw new RuntimeCamelException(e1);
193 } catch (RemoteException e1) {
194 throw new RuntimeCamelException(e1);
195 }
196 }
197 throw new RuntimeCamelException(e);
198 } finally {
199 if (tnx != null) {
200 try {
201 tnx.commit();
202 } catch (UnknownTransactionException e1) {
203 throw new RuntimeCamelException(e1);
204 } catch (RemoteException e1) {
205 throw new RuntimeCamelException(e1);
206 } catch (CannotCommitException e1) {
207 throw new RuntimeCamelException(e1);
208 }
209 }
210 }
211 }
212
213 }