diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2010-08-29 02:55:29 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2010-08-29 02:55:29 +0000 |
commit | 88bf2a256b02e1858993bf097f4dc743d389e3f0 (patch) | |
tree | 298073eb40da33624a95f820e576e049c279e463 /sandbox/sebastien/java/extend/contrib/modules | |
parent | 490374326cf57b0161d053aea3a9f0cedd7d2228 (diff) |
Sandbox to experiment and extend the runtime.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@990479 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sandbox/sebastien/java/extend/contrib/modules')
125 files changed, 12613 insertions, 0 deletions
diff --git a/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/META-INF/MANIFEST.MF b/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..2789db18ee --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/META-INF/MANIFEST.MF @@ -0,0 +1,21 @@ +Manifest-Version: 1.0
+SCA-Version: 1.1
+Bundle-Name: Apache Tuscany SCA Data Binding for Google ProtocolBuffers
+Bundle-Vendor: The Apache Software Foundation
+Bundle-Version: 2.0.0
+Bundle-ManifestVersion: 2
+Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
+Bundle-Description: Apache Tuscany SCA Data Binding for JSON
+Import-Package: javax.xml.namespace,
+ javax.xml.stream,
+ org.apache.tuscany.sca.common.xml.stax;version="2.0.0",
+ org.apache.tuscany.sca.core;version="2.0.0",
+ org.apache.tuscany.sca.databinding;version="2.0.0",
+ org.apache.tuscany.sca.databinding.impl;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef.impl;version="2.0.0";resolution:=optional,
+ org.apache.tuscany.sca.interfacedef.util;version="2.0.0",
+ org.oasisopen.sca.annotation;version="2.0.0"
+Bundle-SymbolicName: org.apache.tuscany.sca.databinding.protobuf
+Bundle-DocURL: http://www.apache.org/
+
diff --git a/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/pom.xml b/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/pom.xml new file mode 100644 index 0000000000..90b5ba1c68 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/pom.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<project> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-modules</artifactId> + <version>2.0-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>tuscany-databinding-protobuf</artifactId> + <name>Apache Tuscany SCA Data Binding for Google ProtocolBuffers</name> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-core-spi</artifactId> + <version>2.0-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-common-xml</artifactId> + <version>2.0-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-databinding</artifactId> + <version>2.0-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>com.google.protobuf</groupId> + <artifactId>protobuf-java</artifactId> + <version>2.3.0</version> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.8.1</version> + <scope>test</scope> + </dependency> + + </dependencies> +</project> diff --git a/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/main/java/org/apache/tuscany/sca/databinding/protobuf/InputStream2Protobuf.java b/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/main/java/org/apache/tuscany/sca/databinding/protobuf/InputStream2Protobuf.java new file mode 100644 index 0000000000..7953e4e5b3 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/main/java/org/apache/tuscany/sca/databinding/protobuf/InputStream2Protobuf.java @@ -0,0 +1,65 @@ +/* + * 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.tuscany.sca.databinding.protobuf; + +import java.io.InputStream; +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; + +import com.google.protobuf.Message; + +/** + * + */ +public class InputStream2Protobuf implements PullTransformer<InputStream, Message> { + + @Override + public String getSourceDataBinding() { + return "application/x-protobuf" + "#" + InputStream.class.getName(); + } + + @Override + public String getTargetDataBinding() { + // TODO Auto-generated method stub + return ProtobufDatabinding.NAME; + } + + @Override + public int getWeight() { + // TODO Auto-generated method stub + return 10; + } + + @Override + public Message transform(InputStream source, TransformationContext context) { + try { + Class<?> type = context.getTargetDataType().getPhysical(); + Method method = type.getMethod("parseFrom", InputStream.class); + Object result = method.invoke(null, source); + return (Message)result; + } catch (Throwable e) { + throw new TransformationException(e); + } + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/main/java/org/apache/tuscany/sca/databinding/protobuf/Protobuf2OutputStream.java b/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/main/java/org/apache/tuscany/sca/databinding/protobuf/Protobuf2OutputStream.java new file mode 100644 index 0000000000..6892287f67 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/main/java/org/apache/tuscany/sca/databinding/protobuf/Protobuf2OutputStream.java @@ -0,0 +1,60 @@ +/* + * 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.tuscany.sca.databinding.protobuf; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.tuscany.sca.databinding.PushTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; + +import com.google.protobuf.Message; + +/** + * + */ +public class Protobuf2OutputStream implements PushTransformer<Message, OutputStream> { + @Override + public String getSourceDataBinding() { + return ProtobufDatabinding.NAME; + } + + @Override + public String getTargetDataBinding() { + return "application/x-protobuf" + "#" + OutputStream.class.getName(); + } + + @Override + public int getWeight() { + return 10; + } + + @Override + public void transform(Message source, OutputStream sink, TransformationContext context) { + try { + if (source != null) { + source.writeTo(sink); + } + } catch (IOException e) { + throw new TransformationException(e); + } + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/main/java/org/apache/tuscany/sca/databinding/protobuf/ProtobufDatabinding.java b/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/main/java/org/apache/tuscany/sca/databinding/protobuf/ProtobufDatabinding.java new file mode 100644 index 0000000000..ad148c7499 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/main/java/org/apache/tuscany/sca/databinding/protobuf/ProtobufDatabinding.java @@ -0,0 +1,107 @@ +/* + * 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.tuscany.sca.databinding.protobuf; + +import org.apache.tuscany.sca.databinding.DataBinding; +import org.apache.tuscany.sca.databinding.WrapperHandler; +import org.apache.tuscany.sca.databinding.XMLTypeHelper; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; + +import com.google.protobuf.Message; + +/** + * Google ProtocolBuffers databinding + */ +public class ProtobufDatabinding implements DataBinding { + + public static final String NAME = "ProtocolBuffers"; + + /** + * + */ + public ProtobufDatabinding() { + } + + /* (non-Javadoc) + * @see org.apache.tuscany.sca.databinding.DataBinding#getName() + */ + @Override + public String getName() { + return NAME; + } + + /* (non-Javadoc) + * @see org.apache.tuscany.sca.databinding.DataBinding#introspect(org.apache.tuscany.sca.interfacedef.DataType, org.apache.tuscany.sca.interfacedef.Operation) + */ + @Override + public boolean introspect(DataType dataType, Operation operation) { + if (Message.class.isAssignableFrom(dataType.getPhysical())) { + dataType.setDataBinding(NAME); + return true; + } + return false; + } + + /* (non-Javadoc) + * @see org.apache.tuscany.sca.databinding.DataBinding#introspect(java.lang.Object, org.apache.tuscany.sca.interfacedef.Operation) + */ + @Override + public DataType introspect(Object value, Operation operation) { + if (value instanceof Message) { + DataType dt = new DataTypeImpl(value.getClass(), null); + dt.setDataBinding(NAME); + return dt; + } else { + return null; + } + } + + /* (non-Javadoc) + * @see org.apache.tuscany.sca.databinding.DataBinding#getWrapperHandler() + */ + @Override + public WrapperHandler getWrapperHandler() { + return null; + } + + /* (non-Javadoc) + * @see org.apache.tuscany.sca.databinding.DataBinding#copy(java.lang.Object, org.apache.tuscany.sca.interfacedef.DataType, org.apache.tuscany.sca.interfacedef.DataType, org.apache.tuscany.sca.interfacedef.Operation, org.apache.tuscany.sca.interfacedef.Operation) + */ + @Override + public Object copy(Object object, + DataType sourceDataType, + DataType targetDataType, + Operation sourceOperation, + Operation targetOperation) { + Message msg = (Message)object; + return ((Message.Builder)msg.toBuilder().clone()).build(); + } + + /* (non-Javadoc) + * @see org.apache.tuscany.sca.databinding.DataBinding#getXMLTypeHelper() + */ + @Override + public XMLTypeHelper getXMLTypeHelper() { + return null; + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding b/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding new file mode 100644 index 0000000000..35f7932ff9 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding @@ -0,0 +1,20 @@ +# 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. + +# implementation classes for the databindings +org.apache.tuscany.sca.databinding.protobuf.ProtobufDatabinding;name=ProtocolBuffers +
diff --git a/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer b/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer new file mode 100644 index 0000000000..0f60373c30 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer @@ -0,0 +1,20 @@ +# 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. + +# Implementation classes for the transformers +org.apache.tuscany.sca.databinding.protobuf.InputStream2Protobuf;source=application/x-protobuf#java.io.InputStream;target=ProtocolBuffers,weight=10,public=true +
diff --git a/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PushTransformer b/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PushTransformer new file mode 100644 index 0000000000..cc1989eb7b --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PushTransformer @@ -0,0 +1,17 @@ +# 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. +org.apache.tuscany.sca.databinding.protobuf.Protobuf2OutputStream;source=ProtocolBuffers;target=application/x-protobuf#java.io.OutputStream,weight=10,public=true diff --git a/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/test/java/com/example/tutorial/AddressBookProtos.java b/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/test/java/com/example/tutorial/AddressBookProtos.java new file mode 100644 index 0000000000..8219fe1099 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/test/java/com/example/tutorial/AddressBookProtos.java @@ -0,0 +1,1375 @@ +/* + * 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. + */ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: addressbook.proto + +package com.example.tutorial; + +public final class AddressBookProtos { + private AddressBookProtos() { + } + + public static void registerAllExtensions(com.google.protobuf.ExtensionRegistry registry) { + } + + public static final class Person extends com.google.protobuf.GeneratedMessage { + // Use Person.newBuilder() to construct. + private Person() { + initFields(); + } + + private Person(boolean noInit) { + } + + private static final Person defaultInstance; + + public static Person getDefaultInstance() { + return defaultInstance; + } + + public Person getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return com.example.tutorial.AddressBookProtos.internal_static_tutorial_Person_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { + return com.example.tutorial.AddressBookProtos.internal_static_tutorial_Person_fieldAccessorTable; + } + + public enum PhoneType implements com.google.protobuf.ProtocolMessageEnum { + MOBILE(0, 0), HOME(1, 1), WORK(2, 2), ; + + public final int getNumber() { + return value; + } + + public static PhoneType valueOf(int value) { + switch (value) { + case 0: + return MOBILE; + case 1: + return HOME; + case 2: + return WORK; + default: + return null; + } + } + + public static com.google.protobuf.Internal.EnumLiteMap<PhoneType> internalGetValueMap() { + return internalValueMap; + } + + private static com.google.protobuf.Internal.EnumLiteMap<PhoneType> internalValueMap = + new com.google.protobuf.Internal.EnumLiteMap<PhoneType>() { + public PhoneType findValueByNumber(int number) { + return PhoneType.valueOf(number); + } + }; + + public final com.google.protobuf.Descriptors.EnumValueDescriptor getValueDescriptor() { + return getDescriptor().getValues().get(index); + } + + public final com.google.protobuf.Descriptors.EnumDescriptor getDescriptorForType() { + return getDescriptor(); + } + + public static final com.google.protobuf.Descriptors.EnumDescriptor getDescriptor() { + return com.example.tutorial.AddressBookProtos.Person.getDescriptor().getEnumTypes().get(0); + } + + private static final PhoneType[] VALUES = {MOBILE, HOME, WORK,}; + + public static PhoneType valueOf(com.google.protobuf.Descriptors.EnumValueDescriptor desc) { + if (desc.getType() != getDescriptor()) { + throw new java.lang.IllegalArgumentException("EnumValueDescriptor is not for this type."); + } + return VALUES[desc.getIndex()]; + } + + private final int index; + private final int value; + + private PhoneType(int index, int value) { + this.index = index; + this.value = value; + } + + static { + com.example.tutorial.AddressBookProtos.getDescriptor(); + } + + // @@protoc_insertion_point(enum_scope:tutorial.Person.PhoneType) + } + + public static final class PhoneNumber extends com.google.protobuf.GeneratedMessage { + // Use PhoneNumber.newBuilder() to construct. + private PhoneNumber() { + initFields(); + } + + private PhoneNumber(boolean noInit) { + } + + private static final PhoneNumber defaultInstance; + + public static PhoneNumber getDefaultInstance() { + return defaultInstance; + } + + public PhoneNumber getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return com.example.tutorial.AddressBookProtos.internal_static_tutorial_Person_PhoneNumber_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { + return com.example.tutorial.AddressBookProtos.internal_static_tutorial_Person_PhoneNumber_fieldAccessorTable; + } + + // required string number = 1; + public static final int NUMBER_FIELD_NUMBER = 1; + private boolean hasNumber; + private java.lang.String number_ = ""; + + public boolean hasNumber() { + return hasNumber; + } + + public java.lang.String getNumber() { + return number_; + } + + // optional .tutorial.Person.PhoneType type = 2 [default = HOME]; + public static final int TYPE_FIELD_NUMBER = 2; + private boolean hasType; + private com.example.tutorial.AddressBookProtos.Person.PhoneType type_; + + public boolean hasType() { + return hasType; + } + + public com.example.tutorial.AddressBookProtos.Person.PhoneType getType() { + return type_; + } + + private void initFields() { + type_ = com.example.tutorial.AddressBookProtos.Person.PhoneType.HOME; + } + + public final boolean isInitialized() { + if (!hasNumber) + return false; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { + getSerializedSize(); + if (hasNumber()) { + output.writeString(1, getNumber()); + } + if (hasType()) { + output.writeEnum(2, getType().getNumber()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) + return size; + + size = 0; + if (hasNumber()) { + size += com.google.protobuf.CodedOutputStream.computeStringSize(1, getNumber()); + } + if (hasType()) { + size += com.google.protobuf.CodedOutputStream.computeEnumSize(2, getType().getNumber()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static com.example.tutorial.AddressBookProtos.Person.PhoneNumber parseFrom(com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + + public static com.example.tutorial.AddressBookProtos.Person.PhoneNumber parseFrom(com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry).buildParsed(); + } + + public static com.example.tutorial.AddressBookProtos.Person.PhoneNumber parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + + public static com.example.tutorial.AddressBookProtos.Person.PhoneNumber parseFrom(byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry).buildParsed(); + } + + public static com.example.tutorial.AddressBookProtos.Person.PhoneNumber parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + + public static com.example.tutorial.AddressBookProtos.Person.PhoneNumber parseFrom(java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry).buildParsed(); + } + + public static com.example.tutorial.AddressBookProtos.Person.PhoneNumber parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + + public static com.example.tutorial.AddressBookProtos.Person.PhoneNumber parseDelimitedFrom(java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + + public static com.example.tutorial.AddressBookProtos.Person.PhoneNumber parseFrom(com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + + public static com.example.tutorial.AddressBookProtos.Person.PhoneNumber parseFrom(com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry).buildParsed(); + } + + public static Builder newBuilder() { + return Builder.create(); + } + + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder(com.example.tutorial.AddressBookProtos.Person.PhoneNumber prototype) { + return newBuilder().mergeFrom(prototype); + } + + public Builder toBuilder() { + return newBuilder(this); + } + + public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder<Builder> { + private com.example.tutorial.AddressBookProtos.Person.PhoneNumber result; + + // Construct using com.example.tutorial.AddressBookProtos.Person.PhoneNumber.newBuilder() + private Builder() { + } + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new com.example.tutorial.AddressBookProtos.Person.PhoneNumber(); + return builder; + } + + protected com.example.tutorial.AddressBookProtos.Person.PhoneNumber internalGetResult() { + return result; + } + + public Builder clear() { + if (result == null) { + throw new IllegalStateException("Cannot call clear() after build()."); + } + result = new com.example.tutorial.AddressBookProtos.Person.PhoneNumber(); + return this; + } + + public Builder clone() { + return create().mergeFrom(result); + } + + public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { + return com.example.tutorial.AddressBookProtos.Person.PhoneNumber.getDescriptor(); + } + + public com.example.tutorial.AddressBookProtos.Person.PhoneNumber getDefaultInstanceForType() { + return com.example.tutorial.AddressBookProtos.Person.PhoneNumber.getDefaultInstance(); + } + + public boolean isInitialized() { + return result.isInitialized(); + } + + public com.example.tutorial.AddressBookProtos.Person.PhoneNumber build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private com.example.tutorial.AddressBookProtos.Person.PhoneNumber buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException(result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + public com.example.tutorial.AddressBookProtos.Person.PhoneNumber buildPartial() { + if (result == null) { + throw new IllegalStateException("build() has already been called on this Builder."); + } + com.example.tutorial.AddressBookProtos.Person.PhoneNumber returnMe = result; + result = null; + return returnMe; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.example.tutorial.AddressBookProtos.Person.PhoneNumber) { + return mergeFrom((com.example.tutorial.AddressBookProtos.Person.PhoneNumber)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.example.tutorial.AddressBookProtos.Person.PhoneNumber other) { + if (other == com.example.tutorial.AddressBookProtos.Person.PhoneNumber.getDefaultInstance()) + return this; + if (other.hasNumber()) { + setNumber(other.getNumber()); + } + if (other.hasType()) { + setType(other.getType()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + public Builder mergeFrom(com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 10: { + setNumber(input.readString()); + break; + } + case 16: { + int rawValue = input.readEnum(); + com.example.tutorial.AddressBookProtos.Person.PhoneType value = + com.example.tutorial.AddressBookProtos.Person.PhoneType.valueOf(rawValue); + if (value == null) { + unknownFields.mergeVarintField(2, rawValue); + } else { + setType(value); + } + break; + } + } + } + } + + // required string number = 1; + public boolean hasNumber() { + return result.hasNumber(); + } + + public java.lang.String getNumber() { + return result.getNumber(); + } + + public Builder setNumber(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasNumber = true; + result.number_ = value; + return this; + } + + public Builder clearNumber() { + result.hasNumber = false; + result.number_ = getDefaultInstance().getNumber(); + return this; + } + + // optional .tutorial.Person.PhoneType type = 2 [default = HOME]; + public boolean hasType() { + return result.hasType(); + } + + public com.example.tutorial.AddressBookProtos.Person.PhoneType getType() { + return result.getType(); + } + + public Builder setType(com.example.tutorial.AddressBookProtos.Person.PhoneType value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasType = true; + result.type_ = value; + return this; + } + + public Builder clearType() { + result.hasType = false; + result.type_ = com.example.tutorial.AddressBookProtos.Person.PhoneType.HOME; + return this; + } + + // @@protoc_insertion_point(builder_scope:tutorial.Person.PhoneNumber) + } + + static { + defaultInstance = new PhoneNumber(true); + com.example.tutorial.AddressBookProtos.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:tutorial.Person.PhoneNumber) + } + + // required string name = 1; + public static final int NAME_FIELD_NUMBER = 1; + private boolean hasName; + private java.lang.String name_ = ""; + + public boolean hasName() { + return hasName; + } + + public java.lang.String getName() { + return name_; + } + + // required int32 id = 2; + public static final int ID_FIELD_NUMBER = 2; + private boolean hasId; + private int id_ = 0; + + public boolean hasId() { + return hasId; + } + + public int getId() { + return id_; + } + + // optional string email = 3; + public static final int EMAIL_FIELD_NUMBER = 3; + private boolean hasEmail; + private java.lang.String email_ = ""; + + public boolean hasEmail() { + return hasEmail; + } + + public java.lang.String getEmail() { + return email_; + } + + // repeated .tutorial.Person.PhoneNumber phone = 4; + public static final int PHONE_FIELD_NUMBER = 4; + private java.util.List<com.example.tutorial.AddressBookProtos.Person.PhoneNumber> phone_ = + java.util.Collections.emptyList(); + + public java.util.List<com.example.tutorial.AddressBookProtos.Person.PhoneNumber> getPhoneList() { + return phone_; + } + + public int getPhoneCount() { + return phone_.size(); + } + + public com.example.tutorial.AddressBookProtos.Person.PhoneNumber getPhone(int index) { + return phone_.get(index); + } + + private void initFields() { + } + + public final boolean isInitialized() { + if (!hasName) + return false; + if (!hasId) + return false; + for (com.example.tutorial.AddressBookProtos.Person.PhoneNumber element : getPhoneList()) { + if (!element.isInitialized()) + return false; + } + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { + getSerializedSize(); + if (hasName()) { + output.writeString(1, getName()); + } + if (hasId()) { + output.writeInt32(2, getId()); + } + if (hasEmail()) { + output.writeString(3, getEmail()); + } + for (com.example.tutorial.AddressBookProtos.Person.PhoneNumber element : getPhoneList()) { + output.writeMessage(4, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) + return size; + + size = 0; + if (hasName()) { + size += com.google.protobuf.CodedOutputStream.computeStringSize(1, getName()); + } + if (hasId()) { + size += com.google.protobuf.CodedOutputStream.computeInt32Size(2, getId()); + } + if (hasEmail()) { + size += com.google.protobuf.CodedOutputStream.computeStringSize(3, getEmail()); + } + for (com.example.tutorial.AddressBookProtos.Person.PhoneNumber element : getPhoneList()) { + size += com.google.protobuf.CodedOutputStream.computeMessageSize(4, element); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static com.example.tutorial.AddressBookProtos.Person parseFrom(com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + + public static com.example.tutorial.AddressBookProtos.Person parseFrom(com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry).buildParsed(); + } + + public static com.example.tutorial.AddressBookProtos.Person parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + + public static com.example.tutorial.AddressBookProtos.Person parseFrom(byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry).buildParsed(); + } + + public static com.example.tutorial.AddressBookProtos.Person parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + + public static com.example.tutorial.AddressBookProtos.Person parseFrom(java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry).buildParsed(); + } + + public static com.example.tutorial.AddressBookProtos.Person parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + + public static com.example.tutorial.AddressBookProtos.Person parseDelimitedFrom(java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + + public static com.example.tutorial.AddressBookProtos.Person parseFrom(com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + + public static com.example.tutorial.AddressBookProtos.Person parseFrom(com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry).buildParsed(); + } + + public static Builder newBuilder() { + return Builder.create(); + } + + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder(com.example.tutorial.AddressBookProtos.Person prototype) { + return newBuilder().mergeFrom(prototype); + } + + public Builder toBuilder() { + return newBuilder(this); + } + + public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder<Builder> { + private com.example.tutorial.AddressBookProtos.Person result; + + // Construct using com.example.tutorial.AddressBookProtos.Person.newBuilder() + private Builder() { + } + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new com.example.tutorial.AddressBookProtos.Person(); + return builder; + } + + protected com.example.tutorial.AddressBookProtos.Person internalGetResult() { + return result; + } + + public Builder clear() { + if (result == null) { + throw new IllegalStateException("Cannot call clear() after build()."); + } + result = new com.example.tutorial.AddressBookProtos.Person(); + return this; + } + + public Builder clone() { + return create().mergeFrom(result); + } + + public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { + return com.example.tutorial.AddressBookProtos.Person.getDescriptor(); + } + + public com.example.tutorial.AddressBookProtos.Person getDefaultInstanceForType() { + return com.example.tutorial.AddressBookProtos.Person.getDefaultInstance(); + } + + public boolean isInitialized() { + return result.isInitialized(); + } + + public com.example.tutorial.AddressBookProtos.Person build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private com.example.tutorial.AddressBookProtos.Person buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException(result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + public com.example.tutorial.AddressBookProtos.Person buildPartial() { + if (result == null) { + throw new IllegalStateException("build() has already been called on this Builder."); + } + if (result.phone_ != java.util.Collections.EMPTY_LIST) { + result.phone_ = java.util.Collections.unmodifiableList(result.phone_); + } + com.example.tutorial.AddressBookProtos.Person returnMe = result; + result = null; + return returnMe; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.example.tutorial.AddressBookProtos.Person) { + return mergeFrom((com.example.tutorial.AddressBookProtos.Person)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.example.tutorial.AddressBookProtos.Person other) { + if (other == com.example.tutorial.AddressBookProtos.Person.getDefaultInstance()) + return this; + if (other.hasName()) { + setName(other.getName()); + } + if (other.hasId()) { + setId(other.getId()); + } + if (other.hasEmail()) { + setEmail(other.getEmail()); + } + if (!other.phone_.isEmpty()) { + if (result.phone_.isEmpty()) { + result.phone_ = + new java.util.ArrayList<com.example.tutorial.AddressBookProtos.Person.PhoneNumber>(); + } + result.phone_.addAll(other.phone_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + public Builder mergeFrom(com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 10: { + setName(input.readString()); + break; + } + case 16: { + setId(input.readInt32()); + break; + } + case 26: { + setEmail(input.readString()); + break; + } + case 34: { + com.example.tutorial.AddressBookProtos.Person.PhoneNumber.Builder subBuilder = + com.example.tutorial.AddressBookProtos.Person.PhoneNumber.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addPhone(subBuilder.buildPartial()); + break; + } + } + } + } + + // required string name = 1; + public boolean hasName() { + return result.hasName(); + } + + public java.lang.String getName() { + return result.getName(); + } + + public Builder setName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasName = true; + result.name_ = value; + return this; + } + + public Builder clearName() { + result.hasName = false; + result.name_ = getDefaultInstance().getName(); + return this; + } + + // required int32 id = 2; + public boolean hasId() { + return result.hasId(); + } + + public int getId() { + return result.getId(); + } + + public Builder setId(int value) { + result.hasId = true; + result.id_ = value; + return this; + } + + public Builder clearId() { + result.hasId = false; + result.id_ = 0; + return this; + } + + // optional string email = 3; + public boolean hasEmail() { + return result.hasEmail(); + } + + public java.lang.String getEmail() { + return result.getEmail(); + } + + public Builder setEmail(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasEmail = true; + result.email_ = value; + return this; + } + + public Builder clearEmail() { + result.hasEmail = false; + result.email_ = getDefaultInstance().getEmail(); + return this; + } + + // repeated .tutorial.Person.PhoneNumber phone = 4; + public java.util.List<com.example.tutorial.AddressBookProtos.Person.PhoneNumber> getPhoneList() { + return java.util.Collections.unmodifiableList(result.phone_); + } + + public int getPhoneCount() { + return result.getPhoneCount(); + } + + public com.example.tutorial.AddressBookProtos.Person.PhoneNumber getPhone(int index) { + return result.getPhone(index); + } + + public Builder setPhone(int index, com.example.tutorial.AddressBookProtos.Person.PhoneNumber value) { + if (value == null) { + throw new NullPointerException(); + } + result.phone_.set(index, value); + return this; + } + + public Builder setPhone(int index, + com.example.tutorial.AddressBookProtos.Person.PhoneNumber.Builder builderForValue) { + result.phone_.set(index, builderForValue.build()); + return this; + } + + public Builder addPhone(com.example.tutorial.AddressBookProtos.Person.PhoneNumber value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.phone_.isEmpty()) { + result.phone_ = + new java.util.ArrayList<com.example.tutorial.AddressBookProtos.Person.PhoneNumber>(); + } + result.phone_.add(value); + return this; + } + + public Builder addPhone(com.example.tutorial.AddressBookProtos.Person.PhoneNumber.Builder builderForValue) { + if (result.phone_.isEmpty()) { + result.phone_ = + new java.util.ArrayList<com.example.tutorial.AddressBookProtos.Person.PhoneNumber>(); + } + result.phone_.add(builderForValue.build()); + return this; + } + + public Builder addAllPhone(java.lang.Iterable<? extends com.example.tutorial.AddressBookProtos.Person.PhoneNumber> values) { + if (result.phone_.isEmpty()) { + result.phone_ = + new java.util.ArrayList<com.example.tutorial.AddressBookProtos.Person.PhoneNumber>(); + } + super.addAll(values, result.phone_); + return this; + } + + public Builder clearPhone() { + result.phone_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:tutorial.Person) + } + + static { + defaultInstance = new Person(true); + com.example.tutorial.AddressBookProtos.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:tutorial.Person) + } + + public static final class AddressBook extends com.google.protobuf.GeneratedMessage { + // Use AddressBook.newBuilder() to construct. + private AddressBook() { + initFields(); + } + + private AddressBook(boolean noInit) { + } + + private static final AddressBook defaultInstance; + + public static AddressBook getDefaultInstance() { + return defaultInstance; + } + + public AddressBook getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return com.example.tutorial.AddressBookProtos.internal_static_tutorial_AddressBook_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { + return com.example.tutorial.AddressBookProtos.internal_static_tutorial_AddressBook_fieldAccessorTable; + } + + // repeated .tutorial.Person person = 1; + public static final int PERSON_FIELD_NUMBER = 1; + private java.util.List<com.example.tutorial.AddressBookProtos.Person> person_ = java.util.Collections + .emptyList(); + + public java.util.List<com.example.tutorial.AddressBookProtos.Person> getPersonList() { + return person_; + } + + public int getPersonCount() { + return person_.size(); + } + + public com.example.tutorial.AddressBookProtos.Person getPerson(int index) { + return person_.get(index); + } + + private void initFields() { + } + + public final boolean isInitialized() { + for (com.example.tutorial.AddressBookProtos.Person element : getPersonList()) { + if (!element.isInitialized()) + return false; + } + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { + getSerializedSize(); + for (com.example.tutorial.AddressBookProtos.Person element : getPersonList()) { + output.writeMessage(1, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) + return size; + + size = 0; + for (com.example.tutorial.AddressBookProtos.Person element : getPersonList()) { + size += com.google.protobuf.CodedOutputStream.computeMessageSize(1, element); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static com.example.tutorial.AddressBookProtos.AddressBook parseFrom(com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + + public static com.example.tutorial.AddressBookProtos.AddressBook parseFrom(com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry).buildParsed(); + } + + public static com.example.tutorial.AddressBookProtos.AddressBook parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + + public static com.example.tutorial.AddressBookProtos.AddressBook parseFrom(byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry).buildParsed(); + } + + public static com.example.tutorial.AddressBookProtos.AddressBook parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + + public static com.example.tutorial.AddressBookProtos.AddressBook parseFrom(java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry).buildParsed(); + } + + public static com.example.tutorial.AddressBookProtos.AddressBook parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + + public static com.example.tutorial.AddressBookProtos.AddressBook parseDelimitedFrom(java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + + public static com.example.tutorial.AddressBookProtos.AddressBook parseFrom(com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + + public static com.example.tutorial.AddressBookProtos.AddressBook parseFrom(com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry).buildParsed(); + } + + public static Builder newBuilder() { + return Builder.create(); + } + + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder(com.example.tutorial.AddressBookProtos.AddressBook prototype) { + return newBuilder().mergeFrom(prototype); + } + + public Builder toBuilder() { + return newBuilder(this); + } + + public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder<Builder> { + private com.example.tutorial.AddressBookProtos.AddressBook result; + + // Construct using com.example.tutorial.AddressBookProtos.AddressBook.newBuilder() + private Builder() { + } + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new com.example.tutorial.AddressBookProtos.AddressBook(); + return builder; + } + + protected com.example.tutorial.AddressBookProtos.AddressBook internalGetResult() { + return result; + } + + public Builder clear() { + if (result == null) { + throw new IllegalStateException("Cannot call clear() after build()."); + } + result = new com.example.tutorial.AddressBookProtos.AddressBook(); + return this; + } + + public Builder clone() { + return create().mergeFrom(result); + } + + public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { + return com.example.tutorial.AddressBookProtos.AddressBook.getDescriptor(); + } + + public com.example.tutorial.AddressBookProtos.AddressBook getDefaultInstanceForType() { + return com.example.tutorial.AddressBookProtos.AddressBook.getDefaultInstance(); + } + + public boolean isInitialized() { + return result.isInitialized(); + } + + public com.example.tutorial.AddressBookProtos.AddressBook build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private com.example.tutorial.AddressBookProtos.AddressBook buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException(result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + public com.example.tutorial.AddressBookProtos.AddressBook buildPartial() { + if (result == null) { + throw new IllegalStateException("build() has already been called on this Builder."); + } + if (result.person_ != java.util.Collections.EMPTY_LIST) { + result.person_ = java.util.Collections.unmodifiableList(result.person_); + } + com.example.tutorial.AddressBookProtos.AddressBook returnMe = result; + result = null; + return returnMe; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.example.tutorial.AddressBookProtos.AddressBook) { + return mergeFrom((com.example.tutorial.AddressBookProtos.AddressBook)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.example.tutorial.AddressBookProtos.AddressBook other) { + if (other == com.example.tutorial.AddressBookProtos.AddressBook.getDefaultInstance()) + return this; + if (!other.person_.isEmpty()) { + if (result.person_.isEmpty()) { + result.person_ = new java.util.ArrayList<com.example.tutorial.AddressBookProtos.Person>(); + } + result.person_.addAll(other.person_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + public Builder mergeFrom(com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 10: { + com.example.tutorial.AddressBookProtos.Person.Builder subBuilder = + com.example.tutorial.AddressBookProtos.Person.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addPerson(subBuilder.buildPartial()); + break; + } + } + } + } + + // repeated .tutorial.Person person = 1; + public java.util.List<com.example.tutorial.AddressBookProtos.Person> getPersonList() { + return java.util.Collections.unmodifiableList(result.person_); + } + + public int getPersonCount() { + return result.getPersonCount(); + } + + public com.example.tutorial.AddressBookProtos.Person getPerson(int index) { + return result.getPerson(index); + } + + public Builder setPerson(int index, com.example.tutorial.AddressBookProtos.Person value) { + if (value == null) { + throw new NullPointerException(); + } + result.person_.set(index, value); + return this; + } + + public Builder setPerson(int index, com.example.tutorial.AddressBookProtos.Person.Builder builderForValue) { + result.person_.set(index, builderForValue.build()); + return this; + } + + public Builder addPerson(com.example.tutorial.AddressBookProtos.Person value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.person_.isEmpty()) { + result.person_ = new java.util.ArrayList<com.example.tutorial.AddressBookProtos.Person>(); + } + result.person_.add(value); + return this; + } + + public Builder addPerson(com.example.tutorial.AddressBookProtos.Person.Builder builderForValue) { + if (result.person_.isEmpty()) { + result.person_ = new java.util.ArrayList<com.example.tutorial.AddressBookProtos.Person>(); + } + result.person_.add(builderForValue.build()); + return this; + } + + public Builder addAllPerson(java.lang.Iterable<? extends com.example.tutorial.AddressBookProtos.Person> values) { + if (result.person_.isEmpty()) { + result.person_ = new java.util.ArrayList<com.example.tutorial.AddressBookProtos.Person>(); + } + super.addAll(values, result.person_); + return this; + } + + public Builder clearPerson() { + result.person_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:tutorial.AddressBook) + } + + static { + defaultInstance = new AddressBook(true); + com.example.tutorial.AddressBookProtos.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:tutorial.AddressBook) + } + + private static com.google.protobuf.Descriptors.Descriptor internal_static_tutorial_Person_descriptor; + private static com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_tutorial_Person_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor internal_static_tutorial_Person_PhoneNumber_descriptor; + private static com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_tutorial_Person_PhoneNumber_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor internal_static_tutorial_AddressBook_descriptor; + private static com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_tutorial_AddressBook_fieldAccessorTable; + + public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { + return descriptor; + } + + private static com.google.protobuf.Descriptors.FileDescriptor descriptor; + static { + java.lang.String[] descriptorData = + {"\n\021addressbook.proto\022\010tutorial\"\332\001\n\006Person" + "\022\014\n\004name\030\001 \002(\t\022\n\n\002id\030\002 \002(\005\022\r\n\005email\030\003 \001(" + + "\t\022+\n\005phone\030\004 \003(\0132\034.tutorial.Person.Phone" + + "Number\032M\n\013PhoneNumber\022\016\n\006number\030\001 \002(\t\022.\n" + + "\004type\030\002 \001(\0162\032.tutorial.Person.PhoneType:" + + "\004HOME\"+\n\tPhoneType\022\n\n\006MOBILE\020\000\022\010\n\004HOME\020\001" + + "\022\010\n\004WORK\020\002\"/\n\013AddressBook\022 \n\006person\030\001 \003(" + + "\0132\020.tutorial.PersonB)\n\024com.example.tutor" + + "ialB\021AddressBookProtos"}; + com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = + new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { + public com.google.protobuf.ExtensionRegistry assignDescriptors(com.google.protobuf.Descriptors.FileDescriptor root) { + descriptor = root; + internal_static_tutorial_Person_descriptor = getDescriptor().getMessageTypes().get(0); + internal_static_tutorial_Person_fieldAccessorTable = + new com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_tutorial_Person_descriptor, + new java.lang.String[] {"Name", + "Id", + "Email", + "Phone",}, + com.example.tutorial.AddressBookProtos.Person.class, + com.example.tutorial.AddressBookProtos.Person.Builder.class); + internal_static_tutorial_Person_PhoneNumber_descriptor = + internal_static_tutorial_Person_descriptor.getNestedTypes().get(0); + internal_static_tutorial_Person_PhoneNumber_fieldAccessorTable = + new com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_tutorial_Person_PhoneNumber_descriptor, + new java.lang.String[] {"Number", + "Type",}, + com.example.tutorial.AddressBookProtos.Person.PhoneNumber.class, + com.example.tutorial.AddressBookProtos.Person.PhoneNumber.Builder.class); + internal_static_tutorial_AddressBook_descriptor = getDescriptor().getMessageTypes().get(1); + internal_static_tutorial_AddressBook_fieldAccessorTable = + new com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_tutorial_AddressBook_descriptor, + new java.lang.String[] {"Person",}, + com.example.tutorial.AddressBookProtos.AddressBook.class, + com.example.tutorial.AddressBookProtos.AddressBook.Builder.class); + return null; + } + }; + com.google.protobuf.Descriptors.FileDescriptor + .internalBuildGeneratedFileFrom(descriptorData, + new com.google.protobuf.Descriptors.FileDescriptor[] {}, + assigner); + } + + public static void internalForceInit() { + } + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/test/java/org/apache/tuscany/sca/databinding/protobuf/ProtobufTransformationTestCase.java b/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/test/java/org/apache/tuscany/sca/databinding/protobuf/ProtobufTransformationTestCase.java new file mode 100644 index 0000000000..9fc6f30794 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/test/java/org/apache/tuscany/sca/databinding/protobuf/ProtobufTransformationTestCase.java @@ -0,0 +1,63 @@ +/* + * 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.tuscany.sca.databinding.protobuf; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +import junit.framework.Assert; + +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.impl.TransformationContextImpl; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.junit.Test; + +import com.example.tutorial.AddressBookProtos.AddressBook; +import com.example.tutorial.AddressBookProtos.Person; + +/** + * + */ +public class ProtobufTransformationTestCase { + @Test + public void testTransform() throws Exception { + Protobuf2OutputStream t1 = new Protobuf2OutputStream(); + TransformationContext context = new TransformationContextImpl(); + DataType dt1 = new DataTypeImpl(AddressBook.class, null); + context.setSourceDataType(dt1); + + AddressBook addressBook = + AddressBook.newBuilder() + .addPerson(Person.newBuilder().setId(1).setEmail("abc@example.com").setName("John Smith").build()) + .build(); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + t1.transform(addressBook, bos, context); + + InputStream2Protobuf t2 = new InputStream2Protobuf(); + context.setSourceDataType(null); + context.setTargetDataType(dt1); + + ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); + AddressBook addressBook2 = (AddressBook)t2.transform(bis, context); + Assert.assertEquals(addressBook, addressBook2); + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/test/resources/addressbook.proto b/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/test/resources/addressbook.proto new file mode 100644 index 0000000000..395320fb22 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/databinding-protobuf/src/test/resources/addressbook.proto @@ -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. +// +// See README.txt for information and build instructions. + +package tutorial; + +option java_package = "com.example.tutorial"; +option java_outer_classname = "AddressBookProtos"; + +message Person { + required string name = 1; + required int32 id = 2; // Unique ID number for this person. + optional string email = 3; + + enum PhoneType { + MOBILE = 0; + HOME = 1; + WORK = 2; + } + + message PhoneNumber { + required string number = 1; + optional PhoneType type = 2 [default = HOME]; + } + + repeated PhoneNumber phone = 4; +} + +// Our address book file is just one of these. +message AddressBook { + repeated Person person = 1; +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/LICENSE b/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/LICENSE @@ -0,0 +1,205 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. + + + diff --git a/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/META-INF/MANIFEST.MF b/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..cab6b5057e --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/META-INF/MANIFEST.MF @@ -0,0 +1,33 @@ +Manifest-Version: 1.0
+Private-Package: org.apache.tuscany.sca.http.tomcat;version="2.0.0",org.
+ apache.tuscany.sca.http.tomcat.module;version="2.0.0"
+Tool: Bnd-0.0.255
+Bundle-Name: Apache Tuscany SCA Tomcat Servlet Host Extension
+Created-By: 1.6.0_07 (Sun Microsystems Inc.)
+Bundle-Vendor: The Apache Software Foundation
+Bundle-Version: 2.0.0
+Bnd-LastModified: 1222833663765
+Bundle-ManifestVersion: 2
+Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
+Bundle-Description: Apache Tuscany SCA Tomcat Servlet Host Extension
+Import-Package: javax.naming,
+ javax.naming.directory,
+ javax.servlet,
+ javax.servlet.http,
+ org.apache.catalina,
+ org.apache.catalina.connector,
+ org.apache.catalina.core,
+ org.apache.catalina.servlets,
+ org.apache.catalina.startup,
+ org.apache.coyote,
+ org.apache.coyote.http11,
+ org.apache.naming.resources,
+ org.apache.tomcat.util.buf,
+ org.apache.tomcat.util.http.mapper,
+ org.apache.tomcat.util.net,
+ org.apache.tuscany.sca.core;version="2.0.0",
+ org.apache.tuscany.sca.host.http;version="2.0.0",
+ org.apache.tuscany.sca.work;version="2.0.0"
+Bundle-SymbolicName: org.apache.tuscany.sca.host.tomcat
+Bundle-DocURL: http://www.apache.org/
+
diff --git a/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/NOTICE b/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/NOTICE new file mode 100644 index 0000000000..25bb89c9b2 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2009 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/pom.xml b/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/pom.xml new file mode 100644 index 0000000000..6f49551591 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/pom.xml @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<project> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-modules</artifactId> + <version>2.0-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>tuscany-host-tomcat</artifactId> + <name>Apache Tuscany SCA Tomcat Servlet Host Extension</name> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-host-http</artifactId> + <version>2.0-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>servlet-api</artifactId> + <version>2.5</version> + </dependency> + + <dependency> + <groupId>org.apache.tomcat</groupId> + <artifactId>catalina</artifactId> + <version>6.0.26</version> + <exclusions> + <exclusion> + <groupId>org.apache.tomcat</groupId> + <artifactId>servlet-api</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.apache.tomcat</groupId> + <artifactId>coyote</artifactId> + <version>6.0.26</version> + <exclusions> + <exclusion> + <groupId>org.apache.tomcat</groupId> + <artifactId>servlet-api</artifactId> + </exclusion> + </exclusions> + </dependency> + </dependencies> + +</project> diff --git a/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/src/main/java/org/apache/tuscany/sca/http/tomcat/ServletWrapper.java b/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/src/main/java/org/apache/tuscany/sca/http/tomcat/ServletWrapper.java new file mode 100644 index 0000000000..a0b384d554 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/src/main/java/org/apache/tuscany/sca/http/tomcat/ServletWrapper.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.tuscany.sca.http.tomcat; + +import javax.servlet.Servlet; +import javax.servlet.ServletException; + +import org.apache.catalina.core.StandardWrapper; + +/** + * A Servlet wrapper. + * + * @version $Rev$ $Date$ + */ +public class ServletWrapper extends StandardWrapper { + private static final long serialVersionUID = 1L; + + private final Servlet servlet; + + public ServletWrapper(Servlet servlet) { + this.servlet = servlet; + } + + @Override + public synchronized Servlet loadServlet() { + return servlet; + } + + @Override + public Servlet getServlet() { + return servlet; + } + + public void initServlet() throws ServletException { + servlet.init(facade); + } + + public void destroyServlet() { + servlet.destroy(); + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/src/main/java/org/apache/tuscany/sca/http/tomcat/TomcatDefaultServlet.java b/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/src/main/java/org/apache/tuscany/sca/http/tomcat/TomcatDefaultServlet.java new file mode 100644 index 0000000000..5d9b65503a --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/src/main/java/org/apache/tuscany/sca/http/tomcat/TomcatDefaultServlet.java @@ -0,0 +1,114 @@ +/* + * 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.tuscany.sca.http.tomcat; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.net.URLConnection; +import java.util.Hashtable; + +import javax.naming.NamingException; +import javax.naming.directory.Attributes; +import javax.naming.directory.BasicAttributes; +import javax.naming.directory.DirContext; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; + +import org.apache.catalina.servlets.DefaultServlet; +import org.apache.naming.resources.FileDirContext; +import org.apache.naming.resources.ProxyDirContext; +import org.apache.naming.resources.Resource; + +/** + * DefaultServlet implementation for Tomcat. + * + * @version $Rev$ $Date$ + */ +public class TomcatDefaultServlet extends DefaultServlet { + private static final long serialVersionUID = -7503581551326796573L; + + private String documentRoot; + private ProxyDirContext proxyDirContext; + + public TomcatDefaultServlet(String servletPath, String documentRoot) { + this.documentRoot = documentRoot; + + DirContext dirContext; + URI uri = URI.create(documentRoot); + if (!"file".equals(uri.getScheme())) { + + dirContext = new FileDirContext() { + @Override + public Attributes getAttributes(String name) throws NamingException { + return new BasicAttributes(); + } + + @Override + public Object lookup(String name) throws NamingException { + + try { + final URL url = new URL(TomcatDefaultServlet.this.documentRoot + name); + return new Resource() { + @Override + public InputStream streamContent() throws IOException { + URLConnection connection = url.openConnection(); + connection.setUseCaches(false); + return connection.getInputStream(); + } + }; + } catch (MalformedURLException e) { + throw new NamingException(e.toString()); + } + } + }; + + } else { + dirContext = new FileDirContext(); + ((FileDirContext)dirContext).setDocBase(uri.getPath()); + } + proxyDirContext = new ProxyDirContext(new Hashtable(), dirContext); + resources = proxyDirContext; + } + + @Override + public void init() throws ServletException { + super.init(); + resources = proxyDirContext; + } + + @Override + public void init(ServletConfig servletConfig) throws ServletException { + super.init(servletConfig); + resources = proxyDirContext; + } + + @Override + protected String getRelativePath(HttpServletRequest request) { + String path = request.getPathInfo(); + if (path == null || path.length() == 0) { + path = "/"; + } + return path; + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/src/main/java/org/apache/tuscany/sca/http/tomcat/TomcatServer.java b/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/src/main/java/org/apache/tuscany/sca/http/tomcat/TomcatServer.java new file mode 100644 index 0000000000..d1a2e5d283 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/src/main/java/org/apache/tuscany/sca/http/tomcat/TomcatServer.java @@ -0,0 +1,701 @@ +/* + * 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.tuscany.sca.http.tomcat; + +import java.beans.PropertyChangeListener; +import java.net.InetAddress; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.net.UnknownHostException; +import java.security.AccessController; +import java.security.KeyStore; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +import javax.servlet.RequestDispatcher; +import javax.servlet.Servlet; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +import org.apache.catalina.Container; +import org.apache.catalina.Context; +import org.apache.catalina.Engine; +import org.apache.catalina.Host; +import org.apache.catalina.Lifecycle; +import org.apache.catalina.LifecycleException; +import org.apache.catalina.Loader; +import org.apache.catalina.connector.Connector; +import org.apache.catalina.core.StandardEngine; +import org.apache.catalina.startup.ContextConfig; +import org.apache.catalina.startup.Embedded; +import org.apache.coyote.http11.Http11Protocol; +import org.apache.tomcat.util.buf.MessageBytes; +import org.apache.tomcat.util.http.mapper.MappingData; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.LifeCycleListener; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.host.http.DefaultResourceServlet; +import org.apache.tuscany.sca.host.http.SecurityContext; +import org.apache.tuscany.sca.host.http.ServletHost; +import org.apache.tuscany.sca.host.http.ServletMappingException; +import org.apache.tuscany.sca.work.WorkScheduler; + +/** + * A Tomcat based implementation of ServletHost. + * + * @version $Rev$ $Date$ + */ +public class TomcatServer implements ServletHost, LifeCycleListener { + private static final Logger logger = Logger.getLogger(TomcatServer.class.getName()); + + private WorkScheduler workScheduler; + private Embedded embedded; + private Map<Integer, Port> ports = new HashMap<Integer, Port>(); + private String contextPath = "/"; + private int defaultPort = 8080; + private int defaultSSLPort = 8443; + + private final class TuscanyLoader implements Loader { + private final ClassLoader tccl; + private boolean delegate; + private boolean reloadable; + private Container container; + private List<String> repos = new ArrayList<String>(); + private List<PropertyChangeListener> listeners = new ArrayList<PropertyChangeListener>(); + + private TuscanyLoader(ClassLoader tccl) { + this.tccl = tccl; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + listeners.add(listener); + } + + public void addRepository(String repository) { + repos.add(repository); + } + + public void backgroundProcess() { + } + + public String[] findRepositories() { + return repos.toArray(new String[repos.size()]); + } + + public Container getContainer() { + return container; + } + + public boolean getDelegate() { + return delegate; + } + + public String getInfo() { + return "Tuscany Loader for Embedded Tomcat"; + } + + public boolean getReloadable() { + return reloadable; + } + + public boolean modified() { + return false; + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + listeners.remove(listener); + } + + public void setContainer(Container container) { + this.container = container; + } + + public void setDelegate(boolean delegate) { + this.delegate = delegate; + } + + public void setReloadable(boolean reloadable) { + this.reloadable = reloadable; + } + + public ClassLoader getClassLoader() { + return tccl; + } + } + + /** + * Represents a port and the server that serves it. + */ + private class Port { + private Engine engine; + private Host host; + private Connector connector; + + private Port(Engine engine, Host host, Connector connector) { + this.engine = engine; + this.host = host; + this.connector = connector; + } + + public Engine getEngine() { + return engine; + } + + public Host getHost() { + return host; + } + + public Connector getConnector() { + return connector; + } + } + + /** + * Constructs a new embedded Tomcat server. + * + */ + public TomcatServer(ExtensionPointRegistry registry, Map<String, String> attributes) { + UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class); + this.workScheduler = utilities.getUtility(WorkScheduler.class); + String port = attributes.get("defaultPort"); + if (port != null) { + defaultPort = Integer.parseInt(port); + } + String sslPort = attributes.get("defaultSSLPort"); + if (sslPort != null) { + defaultPort = Integer.parseInt(sslPort); + } + if (attributes.containsKey("contextPath")) { + contextPath = attributes.get("contextPath"); + } + } + + protected TomcatServer(WorkScheduler workScheduler) { + this.workScheduler = workScheduler; + } + + public void setDefaultPort(int port) { + defaultPort = port; + } + + public int getDefaultPort() { + return defaultPort; + } + + /** + * Stop all the started servers. + */ + public void stop() { + if (embedded != null) { + try { + // embedded.stop(); + embedded.destroy(); + for (Port port : ports.values()) { + port.connector.stop(); + } + } catch (LifecycleException e) { + throw new IllegalStateException(e); + } + } + } + + public synchronized String addServletMapping(String suri, Servlet servlet) { + init(); + URI uri = URI.create(suri); + + // Get the URI scheme and port + String scheme = uri.getScheme(); + if (scheme == null) { + scheme = "http"; + } + final int portNumber = (uri.getPort() == -1 ? defaultPort : uri.getPort()); + + // Get the port object associated with the given port number + Port port = ports.get(portNumber); + if (port == null) { + + port = createInstance(scheme, portNumber); + ports.put(portNumber, port); + } + + // Register the Servlet mapping + String path = uri.getPath(); + + if (!path.startsWith("/")) { + path = '/' + path; + } + + if (!path.startsWith(contextPath)) { + path = contextPath + path; + } + + ServletWrapper wrapper; + if (servlet instanceof DefaultResourceServlet) { + String defaultServletPath = path; + + // Optimize the handling of resource requests, use the Tomcat default Servlet + // instead of our default resource Servlet + if (defaultServletPath.endsWith("*")) { + defaultServletPath = defaultServletPath.substring(0, defaultServletPath.length() - 1); + } + if (defaultServletPath.endsWith("/")) { + defaultServletPath = defaultServletPath.substring(0, defaultServletPath.length() - 1); + } + DefaultResourceServlet resourceServlet = (DefaultResourceServlet)servlet; + TomcatDefaultServlet defaultServlet = + new TomcatDefaultServlet(defaultServletPath, resourceServlet.getDocumentRoot()); + wrapper = new ServletWrapper(defaultServlet); + + } else { + wrapper = new ServletWrapper(servlet); + } + Context context = port.getHost().map(path); + wrapper.setName(path); + wrapper.addMapping(path); + context.addChild(wrapper); + context.addServletMapping(path, path); + port.getConnector().getMapper().addWrapper("localhost", "", path, wrapper); + + // Initialize the Servlet + try { + wrapper.initServlet(); + } catch (ServletException e) { + throw new ServletMappingException(e); + } + + // Compute the complete URL + String host; + try { + host = InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException e) { + host = "localhost"; + } + URL addedURL; + try { + addedURL = new URL(scheme, host, portNumber, path); + } catch (MalformedURLException e) { + throw new ServletMappingException(e); + } + logger.info("Added Servlet mapping: " + addedURL); + return addedURL.toString(); + } + + private Port createInstance(String scheme, final int portNumber) { + Port port; + // Create an engine + // Allow privileged access to read properties. Requires PropertiesPermission read in + // security policy. + final Engine engine = AccessController.doPrivileged(new PrivilegedAction<Engine>() { + public Engine run() { + return embedded.createEngine(); + } + }); + + ((StandardEngine)engine).setBaseDir(""); + engine.setDefaultHost("localhost"); + engine.setName("engine/" + portNumber); + + // Create a host + // Allow privileged access to read properties. Requires PropertiesPermission read in + // security policy. + final Host host = AccessController.doPrivileged(new PrivilegedAction<Host>() { + public Host run() { + Host host = embedded.createHost("localhost", ""); + engine.addChild(host); + return host; + } + }); + + // Create the root context + Context context = embedded.createContext("", ""); + final ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + context.setLoader(new TuscanyLoader(tccl)); + // context.setParentClassLoader(tccl.getParent()); + ContextConfig config = new ContextConfig(); + ((Lifecycle)context).addLifecycleListener(config); + host.addChild(context); + + embedded.addEngine(engine); + + // Install an HTTP connector + + Connector connector; + // Allow privileged access to read properties. Requires PropertiesPermission read in + // security policy. + try { + final String protocol = scheme; + connector = AccessController.doPrivileged(new PrivilegedExceptionAction<Connector>() { + public Connector run() throws Exception { + Connector customConnector = new Connector(); + customConnector.setPort(portNumber); + + if ("https".equalsIgnoreCase(protocol)) { + configureSSL(customConnector); + ((Http11Protocol)customConnector.getProtocolHandler()).setSSLEnabled(true); + } + return customConnector; + } + + private void configureSSL(Connector customConnector) { + String trustStore = System.getProperty("javax.net.ssl.trustStore"); + String trustStorePass = System.getProperty("javax.net.ssl.trustStorePassword"); + String keyStore = System.getProperty("javax.net.ssl.keyStore"); + String keyStorePass = System.getProperty("javax.net.ssl.keyStorePassword"); + + customConnector.setProperty("protocol", "TLS"); + + customConnector.setProperty("keystore", keyStore); + customConnector.setProperty("keypass", keyStorePass); + String keyStoreType = System.getProperty("javax.net.ssl.keyStoreType", KeyStore.getDefaultType()); + String trustStoreType = + System.getProperty("javax.net.ssl.trustStoreType", KeyStore.getDefaultType()); + customConnector.setProperty("keytype", keyStoreType); + customConnector.setProperty("trusttype", trustStoreType); + customConnector.setProperty("truststore", trustStore); + customConnector.setProperty("trustpass", trustStorePass); + + customConnector.setProperty("clientauth", "false"); + customConnector.setProtocol("HTTP/1.1"); + customConnector.setScheme(protocol); + customConnector.setProperty("backlog", "10"); + customConnector.setSecure(true); + } + }); + } catch (Exception e) { + throw new ServletMappingException(e); + } + + embedded.addConnector(connector); + try { + connector.start(); + } catch (LifecycleException e) { + throw new ServletMappingException(e); + } + + // Keep track of the running server + port = new Port(engine, host, connector); + return port; + } + + private synchronized void init() { + if (embedded != null) { + return; + } + embedded = new Embedded(); + embedded.setAwait(true); + // Allow privileged access to read properties. Requires PropertiesPermission read in + // security policy. + try { + AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { + public Object run() throws LifecycleException { + embedded.start(); + return null; + } + }); + } catch (PrivilegedActionException e) { + // throw (LifecycleException)e.getException(); + throw new ServletMappingException(e); + } + } + + public URL getURLMapping(String suri) throws ServletMappingException { + URI uri = URI.create(suri); + + // Get the URI scheme and port + String scheme = uri.getScheme(); + if (scheme == null) { + scheme = "http"; + } + int portNumber = uri.getPort(); + if (portNumber == -1) { + portNumber = defaultPort; + } + + // Get the host + String host; + try { + host = InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException e) { + host = "localhost"; + } + + // Construct the URL + String path = uri.getPath(); + + if (!path.startsWith("/")) { + path = '/' + path; + } + + if (!path.startsWith(contextPath)) { + path = contextPath + path; + } + URL url; + try { + url = new URL(scheme, host, portNumber, path); + } catch (MalformedURLException e) { + throw new ServletMappingException(e); + } + return url; + } + + public Servlet getServletMapping(String suri) throws ServletMappingException { + + if (suri == null) { + return null; + } + + URI uri = URI.create(suri); + + // Get the URI port + int portNumber = uri.getPort(); + if (portNumber == -1) { + portNumber = defaultPort; + } + + // Get the port object associated with the given port number + Port port = ports.get(portNumber); + if (port == null) { + return null; + } + + String mapping = uri.getPath(); + + if (!mapping.startsWith("/")) { + mapping = '/' + mapping; + } + + if (!mapping.startsWith(contextPath)) { + mapping = contextPath + mapping; + } + + final Context context = port.getHost().map(mapping); + final MappingData md = new MappingData(); + final MessageBytes mb = MessageBytes.newInstance(); + mb.setString(mapping); + try { + // Allow privileged access to read properties. Requires PropertiesPermission read in + // security policy. + AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { + public Object run() throws Exception { + context.getMapper().map(mb, md); + return null; + } + }); + } catch (Exception e) { + return null; + } + if (md.wrapper instanceof ServletWrapper) { + ServletWrapper servletWrapper = (ServletWrapper)md.wrapper; + return servletWrapper.getServlet(); + } else { + return null; + } + } + + public synchronized Servlet removeServletMapping(String suri) { + URI uri = URI.create(suri); + + // Get the URI port + int portNumber = uri.getPort(); + if (portNumber == -1) { + portNumber = defaultPort; + } + + // Get the port object associated with the given port number + Port port = ports.get(portNumber); + if (port == null) { + throw new IllegalStateException("No servlet registered at this URI: " + suri); + } + + String mapping = uri.getPath(); + + if (!mapping.startsWith("/")) { + mapping = '/' + mapping; + } + + if (!mapping.startsWith(contextPath)) { + mapping = contextPath + mapping; + } + + final Context context = port.getHost().map(mapping); + final MappingData md = new MappingData(); + final MessageBytes mb = MessageBytes.newInstance(); + mb.setString(mapping); + try { + // Allow privileged access to read properties. Requires PropertiesPermission read in + // security policy. + AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { + public Object run() throws Exception { + context.getMapper().map(mb, md); + return null; + } + }); + } catch (Exception e) { + return null; + } + if (md.wrapper instanceof ServletWrapper) { + ServletWrapper servletWrapper = (ServletWrapper)md.wrapper; + + port.getConnector().getMapper().removeWrapper("localhost", "", mapping); + + try { + context.removeServletMapping(mapping); + } catch (NegativeArraySizeException e) { + // JIRA TUSCANY-1599 + // FIXME Looks like a bug in Tomcat when removing the last + // Servlet in the list, catch the exception for now as it doesn't + // seem harmful, will find a better solution for the next release + } + context.removeChild(servletWrapper); + try { + servletWrapper.destroyServlet(); + } catch (Exception ex) { + // Hack to handle destruction of Servlets without Servlet context + } + + logger.info("Removed Servlet mapping: " + suri); + + // Stop the port if there's no servlets on it anymore + String[] contextNames = port.getConnector().getMapper().getContextNames(); + if (contextNames == null || contextNames.length == 0) { + try { + port.getConnector().stop(); + ((StandardEngine)port.getEngine()).stop(); + embedded.removeEngine(port.getEngine()); + embedded.removeConnector(port.getConnector()); + ports.remove(portNumber); + } catch (LifecycleException e) { + throw new IllegalStateException(e); + } + } + + return servletWrapper.getServlet(); + } else { + logger.warning("Trying to Remove servlet mapping: " + mapping + " where mapping is not registered"); + return null; + } + } + + public RequestDispatcher getRequestDispatcher(String suri) throws ServletMappingException { + //FIXME implement this later + return null; + } + + public String getContextPath() { + return contextPath; + } + + public void setContextPath(String path) { + this.contextPath = path; + } + + public void start() { + + } + + public String addServletMapping(String uri, Servlet servlet, SecurityContext securityContext) + throws ServletMappingException { + return addServletMapping(uri, servlet); + } + + public String getName() { + return "tomcat"; + } + + public URL getURLMapping(String arg0, SecurityContext arg1) { + return null; + } + + public void setAttribute(String arg0, Object arg1) { + } + + private URL map(String suri, SecurityContext securityContext, boolean resolve) throws ServletMappingException { + URI uri = URI.create(suri); + + // Get the URI scheme and port + String scheme = null; + if (securityContext != null && securityContext.isSSLEnabled()) { + scheme = "https"; + } else { + scheme = uri.getScheme(); + if (scheme == null) { + scheme = "http"; + } + } + + int portNumber = uri.getPort(); + if (portNumber == -1) { + if ("http".equals(scheme)) { + portNumber = defaultPort; + } else { + portNumber = defaultSSLPort; + } + } + + // Get the host + String host = uri.getHost(); + if (host == null) { + host = "0.0.0.0"; + if (resolve) { + try { + host = InetAddress.getLocalHost().getHostAddress(); + } catch (UnknownHostException e) { + host = "localhost"; + } + } + } + + // Construct the URL + String path = uri.getPath(); + + if (!path.startsWith("/")) { + path = '/' + path; + } + + if (!path.startsWith(contextPath)) { + path = contextPath + path; + } + + URL url; + try { + url = new URL(scheme, host, portNumber, path); + } catch (MalformedURLException e) { + throw new ServletMappingException(e); + } + return url; + } + + @Override + public ServletContext getServletContext() { + if (ports.isEmpty()) { + return null; + } else { + Port port = ports.values().iterator().next(); + return port.getHost().map(getContextPath()).getServletContext(); + } + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/src/main/resources/META-INF/services/org.apache.tuscany.sca.host.http.ServletHost b/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/src/main/resources/META-INF/services/org.apache.tuscany.sca.host.http.ServletHost new file mode 100644 index 0000000000..00350bbf6b --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/src/main/resources/META-INF/services/org.apache.tuscany.sca.host.http.ServletHost @@ -0,0 +1,18 @@ +# 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.
+# Implementation class for the ServletHost
+org.apache.tuscany.sca.http.tomcat.TomcatServer;name=tomcat,ranking=50,defaultPort=8085
diff --git a/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/src/test/java/org/apache/tuscany/sca/http/tomcat/TomcatServerTestCase.java b/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/src/test/java/org/apache/tuscany/sca/http/tomcat/TomcatServerTestCase.java new file mode 100644 index 0000000000..4bcf0623e8 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/src/test/java/org/apache/tuscany/sca/http/tomcat/TomcatServerTestCase.java @@ -0,0 +1,372 @@ +/* + * 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.tuscany.sca.http.tomcat; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.Socket; +import java.net.URL; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSession; +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 junit.framework.TestCase; + +import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.host.http.DefaultResourceServlet; +import org.apache.tuscany.sca.host.http.ExtensibleServletHost; +import org.apache.tuscany.sca.host.http.ServletHost; +import org.apache.tuscany.sca.work.NotificationListener; +import org.apache.tuscany.sca.work.WorkScheduler; +import org.junit.Assert; +import org.junit.Test; + +/** + * @version $Rev$ $Date$ + */ +public class TomcatServerTestCase extends TestCase { + + private static final String REQUEST1_HEADER = + "GET /foo HTTP/1.0\n" + "Host: localhost\n" + + "Content-Type: text/xml\n" + + "Connection: close\n" + + "Content-Length: "; + private static final String REQUEST1_CONTENT = ""; + private static final String REQUEST1 = + REQUEST1_HEADER + REQUEST1_CONTENT.getBytes().length + "\n\n" + REQUEST1_CONTENT; + + private static final String REQUEST2_HEADER = + "GET /webcontent/test.html HTTP/1.0\n" + "Host: localhost\n" + + "Content-Type: text/xml\n" + + "Connection: close\n" + + "Content-Length: "; + private static final String REQUEST2_CONTENT = ""; + private static final String REQUEST2 = + REQUEST2_HEADER + REQUEST2_CONTENT.getBytes().length + "\n\n" + REQUEST2_CONTENT; + + private static final int HTTP_PORT = 8085; + + private WorkScheduler workScheduler = new WorkScheduler() { + + public <T extends Runnable> void scheduleWork(T work) { + Thread thread = new Thread(work); + thread.start(); + } + + public <T extends Runnable> void scheduleWork(T work, NotificationListener<T> listener) { + scheduleWork(work); + } + + public void destroy() { + } + }; + + /** + * Verifies requests are properly routed according to the Servlet mapping + */ + public void testRegisterServletMapping() throws Exception { + TomcatServer service = new TomcatServer(workScheduler); + TestServlet servlet = new TestServlet(); + service.addServletMapping("http://127.0.0.1:" + HTTP_PORT + "/foo", servlet); + ServletContext servletContext = service.getServletContext(); + Assert.assertNotNull(servletContext); + Socket client = new Socket("127.0.0.1", HTTP_PORT); + OutputStream os = client.getOutputStream(); + os.write(REQUEST1.getBytes()); + os.flush(); + read(client); + service.stop(); + assertTrue(servlet.invoked); + } + + /** + * Verifies requests are properly routed according to the Servlet mapping + */ + public void testRegisterServletMappingSSL() throws Exception { + System.setProperty("javax.net.ssl.keyStore", "target/test-classes/tuscany.keyStore"); + System.setProperty("javax.net.ssl.keyStorePassword", "apache"); + TomcatServer service = new TomcatServer(workScheduler); + TestServlet servlet = new TestServlet(); + try { + service.addServletMapping("https://127.0.0.1:" + HTTP_PORT + "/foo", servlet); + } finally { + System.clearProperty("javax.net.ssl.keyStore"); + System.clearProperty("javax.net.ssl.keyStorePassword"); + } + System.setProperty("javax.net.ssl.trustStore", "target/test-classes/tuscany.keyStore"); + System.setProperty("javax.net.ssl.trustStorePassword", "apache"); + URL url = new URL("https://127.0.0.1:8085/foo"); + HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); + conn.setHostnameVerifier(new HostnameVerifier() { + public boolean verify(String hostname, SSLSession session) { + return true; + }} + ); + + conn.connect(); + read(conn.getInputStream()); + + service.stop(); + assertTrue(servlet.invoked); + + } + /** + * Verifies that Servlets can be registered with multiple ports + */ + public void testRegisterMultiplePorts() throws Exception { + TomcatServer service = new TomcatServer(workScheduler); + TestServlet servlet = new TestServlet(); + service.addServletMapping("http://127.0.0.1:" + HTTP_PORT + "/", servlet); + TestServlet servlet2 = new TestServlet(); + service.addServletMapping("http://127.0.0.1:" + (HTTP_PORT + 1) + "/", servlet2); + { + Socket client = new Socket("127.0.0.1", HTTP_PORT); + OutputStream os = client.getOutputStream(); + os.write(REQUEST1.getBytes()); + os.flush(); + read(client); + } + { + Socket client = new Socket("127.0.0.1", HTTP_PORT + 1); + OutputStream os = client.getOutputStream(); + os.write(REQUEST1.getBytes()); + os.flush(); + read(client); + } + + service.stop(); + assertTrue(servlet.invoked); + assertTrue(servlet2.invoked); + } + + public void testUnregisterMapping() throws Exception { + TomcatServer service = new TomcatServer(workScheduler); + TestServlet servlet = new TestServlet(); + service.addServletMapping("http://127.0.0.1:" + HTTP_PORT + "/foo", servlet); + service.removeServletMapping("http://127.0.0.1:" + HTTP_PORT + "/foo"); + Socket client = new Socket("127.0.0.1", HTTP_PORT); + OutputStream os = client.getOutputStream(); + os.write(REQUEST1.getBytes()); + os.flush(); + read(client); + service.stop(); + assertFalse(servlet.invoked); + + } + + public void testRegisterUnregisterMapping() throws Exception { + TomcatServer service = new TomcatServer(workScheduler); + TestServlet servlet = new TestServlet(); + service.addServletMapping("http://127.0.0.1:" + HTTP_PORT + "/foo", servlet); + { + Socket client = new Socket("127.0.0.1", HTTP_PORT); + OutputStream os = client.getOutputStream(); + os.write(REQUEST1.getBytes()); + os.flush(); + read(client); + } + assertTrue(servlet.invoked); + service.removeServletMapping("http://127.0.0.1:" + HTTP_PORT + "/foo"); + { + Socket client = new Socket("127.0.0.1", HTTP_PORT); + OutputStream os = client.getOutputStream(); + os.write(REQUEST1.getBytes()); + os.flush(); + read(client); + } + servlet = new TestServlet(); + service.addServletMapping("http://127.0.0.1:" + HTTP_PORT + "/foo", servlet); + { + Socket client = new Socket("127.0.0.1", HTTP_PORT); + OutputStream os = client.getOutputStream(); + os.write(REQUEST1.getBytes()); + os.flush(); + read(client); + } + assertTrue(servlet.invoked); + service.stop(); + } + + public void testRequestSession() throws Exception { + TomcatServer service = new TomcatServer(workScheduler); + TestServlet servlet = new TestServlet(); + service.addServletMapping("http://127.0.0.1:" + HTTP_PORT + "/foo", servlet); + Socket client = new Socket("127.0.0.1", HTTP_PORT); + OutputStream os = client.getOutputStream(); + os.write(REQUEST1.getBytes()); + os.flush(); + read(client); + service.stop(); + assertTrue(servlet.invoked); + assertNotNull(servlet.sessionId); + } + + public void testRestart() throws Exception { + TomcatServer service = new TomcatServer(workScheduler); + service.stop(); + service.stop(); + } + + public void testNoMappings() throws Exception { + TomcatServer service = new TomcatServer(workScheduler); + Exception ex = null; + try { + Socket client = new Socket("127.0.0.1", HTTP_PORT); + OutputStream os = client.getOutputStream(); + os.write(REQUEST1.getBytes()); + os.flush(); + } catch (Exception e) { + ex = e; + } + assertNotNull(ex); + service.stop(); + } + + public void testResourceServlet() throws Exception { + TomcatServer service = new TomcatServer(workScheduler); + + String documentRoot = getClass().getClassLoader().getResource("content/test.html").toString(); + documentRoot = documentRoot.substring(0, documentRoot.lastIndexOf('/')); + DefaultResourceServlet resourceServlet = new DefaultResourceServlet(documentRoot); + TestResourceServlet servlet = new TestResourceServlet(resourceServlet); + service.addServletMapping("http://127.0.0.1:" + HTTP_PORT + "/webcontent/*", servlet); + + Socket client = new Socket("127.0.0.1", HTTP_PORT); + OutputStream os = client.getOutputStream(); + os.write(REQUEST2.getBytes()); + os.flush(); + + String document = read(client); + assertTrue(document.indexOf("<body><p>hello</body>") != -1); + + service.stop(); + } + + public void testDefaultServlet() throws Exception { + TomcatServer service = new TomcatServer(workScheduler); + + String documentRoot = getClass().getClassLoader().getResource("content/test.html").toString(); + documentRoot = documentRoot.substring(0, documentRoot.lastIndexOf('/')); + DefaultResourceServlet resourceServlet = new DefaultResourceServlet(documentRoot); + service.addServletMapping("http://127.0.0.1:" + HTTP_PORT + "/webcontent/*", resourceServlet); + + Socket client = new Socket("127.0.0.1", HTTP_PORT); + OutputStream os = client.getOutputStream(); + os.write(REQUEST2.getBytes()); + os.flush(); + + String document = read(client); + assertTrue(document.indexOf("<body><p>hello</body>") != -1); + + service.stop(); + } + + private static String read(Socket socket) throws IOException { + InputStream is = socket.getInputStream(); + return read(is); + } + + private static String read(InputStream is) throws IOException { + BufferedReader reader = null; + try { + reader = new BufferedReader(new InputStreamReader(is)); + StringBuffer sb = new StringBuffer(); + String str; + while ((str = reader.readLine()) != null) { + sb.append(str); + } + return sb.toString(); + } finally { + if (reader != null) { + reader.close(); + } + } + } + private class TestServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + boolean invoked; + String sessionId; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + invoked = true; + sessionId = req.getSession().getId(); + OutputStream writer = resp.getOutputStream(); + try { + writer.write("result".getBytes()); + } finally { + writer.close(); + } + } + + } + + private class TestResourceServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + private HttpServlet delegate; + + public TestResourceServlet(HttpServlet delegate) { + this.delegate = delegate; + } + + @Override + public void init() throws ServletException { + super.init(); + delegate.init(); + } + + @Override + public void init(ServletConfig config) throws ServletException { + super.init(); + delegate.init(config); + } + + @Override + protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + delegate.service(req, resp); + } + + @Override + public void destroy() { + super.destroy(); + delegate.destroy(); + } + } + + @Test + public void testDiscovery() { + ExtensionPointRegistry registry = new DefaultExtensionPointRegistry(); + ExtensibleServletHost host = ExtensibleServletHost.getInstance(registry); + ServletHost me = host.getDefaultServletHost(); + Assert.assertEquals("tomcat", me.getName()); + Assert.assertEquals(8085, me.getDefaultPort()); + registry.stop(); + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/src/test/resources/content/test.html b/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/src/test/resources/content/test.html new file mode 100644 index 0000000000..f4b79d7f01 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/src/test/resources/content/test.html @@ -0,0 +1,21 @@ +<html> +<!-- + * 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. +--> +<body><p>hello</body> +</html>
\ No newline at end of file diff --git a/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/src/test/resources/tuscany.keyStore b/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/src/test/resources/tuscany.keyStore Binary files differnew file mode 100644 index 0000000000..7ea23f7ff4 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/host-tomcat/src/test/resources/tuscany.keyStore diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/LICENSE b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/LICENSE new file mode 100644 index 0000000000..6e529a25c4 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/LICENSE @@ -0,0 +1,205 @@ +
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed 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.
+
+
+
diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/META-INF/MANIFEST.MF b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..b598607625 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/META-INF/MANIFEST.MF @@ -0,0 +1,63 @@ +Manifest-Version: 1.0
+SCA-Version: 1.1
+Bundle-Name: Apache Tuscany SCA Spring Implementation Runtime Model
+Bundle-Vendor: The Apache Software Foundation
+Bundle-Version: 2.0.0
+Bundle-ManifestVersion: 2
+Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
+Bundle-Description: Apache Tuscany SCA Spring Implementation Runtime Model
+Bundle-SymbolicName: org.apache.tuscany.sca.implementation.spring.runtime
+Bundle-DocURL: http://www.apache.org/
+Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6 +Import-Package: org.oasisopen.sca;version="2.0.0",
+ org.oasisopen.sca.annotation;version="2.0.0",
+ javax.xml.namespace,
+ org.apache.tuscany.sca.assembly;version="2.0.0",
+ org.apache.tuscany.sca.assembly.builder;version="2.0.0",
+ org.apache.tuscany.sca.assembly.impl;version="2.0.0",
+ org.apache.tuscany.sca.assembly.xml;version="2.0.0",
+ org.apache.tuscany.sca.context;version="2.0.0",
+ org.apache.tuscany.sca.contribution;version="2.0.0",
+ org.apache.tuscany.sca.contribution.processor;version="2.0.0",
+ org.apache.tuscany.sca.contribution.resolver;version="2.0.0",
+ org.apache.tuscany.sca.core;version="2.0.0",
+ org.apache.tuscany.sca.core.factory;version="2.0.0",
+ org.apache.tuscany.sca.core.invocation;version="2.0.0",
+ org.apache.tuscany.sca.databinding;version="2.0.0",
+ org.apache.tuscany.sca.databinding.impl;version="2.0.0",
+ org.apache.tuscany.sca.implementation.spring;version="2.0.0",
+ org.apache.tuscany.sca.implementation.spring.xml;version="2.0.0",
+ org.apache.tuscany.sca.implementation.java;version="2.0.0",
+ org.apache.tuscany.sca.implementation.java.injection;version="2.0.0",
+ org.apache.tuscany.sca.implementation.java.introspect;version="2.0.0",
+ org.apache.tuscany.sca.implementation.java.introspect.impl;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef.java;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef.java.impl;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef.util;version="2.0.0",
+ org.apache.tuscany.sca.invocation;version="2.0.0",
+ org.apache.tuscany.sca.monitor;version="2.0.0",
+ org.apache.tuscany.sca.policy;version="2.0.0",
+ org.apache.tuscany.sca.provider;version="2.0.0",
+ org.apache.tuscany.sca.runtime;version="2.0.0",
+ org.springframework.beans;version="3.0.2.RELEASE",
+ org.springframework.beans.factory;version="3.0.2.RELEASE",
+ org.springframework.beans.factory.annotation;version="3.0.2.RELEASE",
+ org.springframework.beans.factory.config;version="3.0.2.RELEASE",
+ org.springframework.beans.factory.support;version="3.0.2.RELEASE",
+ org.springframework.beans.factory.xml;version="3.0.2.RELEASE",
+ org.springframework.context;version="3.0.2.RELEASE",
+ org.springframework.context.support;version="3.0.2.RELEASE",
+ org.springframework.core;version="3.0.2.RELEASE",
+ org.springframework.core.io;version="3.0.2.RELEASE",
+ org.springframework.util;version="3.0.2.RELEASE"
+Export-Package: org.apache.tuscany.sca.implementation.spring.context;version="2.0.0";
+ uses:="org.springframework.beans.factory.support,
+ org.springframework.context.support,
+ org.springframework.core.io,
+ org.apache.tuscany.sca.implementation.spring,
+ org.springframework.context,
+ org.apache.tuscany.sca.implementation.spring.provider,
+ org.springframework.beans.factory.config,
+ org.springframework.beans.factory"
+
diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/NOTICE b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/NOTICE new file mode 100644 index 0000000000..1325efd8bf --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/NOTICE @@ -0,0 +1,6 @@ +${pom.name}
+Copyright (c) 2005 - 2008 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/pom.xml b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/pom.xml new file mode 100644 index 0000000000..b08e1c8930 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/pom.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<project> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-modules</artifactId> + <version>2.0-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>tuscany-implementation-spring-runtime</artifactId> + <name>Apache Tuscany SCA Spring Implementation Runtime Model</name> + + <dependencies> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-implementation-spring</artifactId> + <version>2.0-SNAPSHOT</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-core</artifactId> + <version>2.0-SNAPSHOT</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-implementation-java-runtime</artifactId> + <version>2.0-SNAPSHOT</version> + <scope>runtime</scope> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-core-spi</artifactId> + <version>2.0-SNAPSHOT</version> + <scope>compile</scope> + </dependency> + + <!-- Spring dependencies... --> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-core</artifactId> + <version>3.0.2.RELEASE</version> + </dependency> + + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-beans</artifactId> + <version>3.0.2.RELEASE</version> + </dependency> + + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-context</artifactId> + <version>3.0.2.RELEASE</version> + </dependency> + + </dependencies> +</project> diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/context/SCAGenericApplicationContext.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/context/SCAGenericApplicationContext.java new file mode 100644 index 0000000000..44a3ee2b88 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/context/SCAGenericApplicationContext.java @@ -0,0 +1,145 @@ +/* + * 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.tuscany.sca.implementation.spring.context; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.implementation.spring.SpringBeanElement; +import org.apache.tuscany.sca.implementation.spring.SpringConstructorArgElement; +import org.apache.tuscany.sca.implementation.spring.SpringPropertyElement; +import org.apache.tuscany.sca.implementation.spring.SpringSCAPropertyElement; +import org.apache.tuscany.sca.implementation.spring.SpringSCAReferenceElement; +import org.apache.tuscany.sca.implementation.spring.SpringSCAServiceElement; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.beans.PropertyValue; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanReference; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.config.ConstructorArgumentValues; +import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder; +import org.springframework.beans.factory.config.TypedStringValue; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.GenericApplicationContext; + +public class SCAGenericApplicationContext extends GenericApplicationContext { + + private ClassLoader classloader = null; + private List<SpringSCAPropertyElement> propertyElements = new ArrayList<SpringSCAPropertyElement>(); + private List<SpringSCAServiceElement> serviceElements = new ArrayList<SpringSCAServiceElement>(); + private List<SpringSCAReferenceElement> referenceElements = new ArrayList<SpringSCAReferenceElement>(); + private List<SpringBeanElement> beanElements; + + public SCAGenericApplicationContext(DefaultListableBeanFactory beanFactory, + ApplicationContext parent, + ClassLoader classloader) { + super(beanFactory, parent); + this.classloader = classloader; + } + + public SCAGenericApplicationContext(ApplicationContext parent, ClassLoader classloader) { + super(parent); + this.classloader = classloader; + } + + @Override + protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { + beanFactory.setBeanClassLoader(classloader); + } + + public void addSCAPropertyElement(SpringSCAPropertyElement propertyElement) { + propertyElements.add(propertyElement); + } + + public void addSCAServiceElement(SpringSCAServiceElement serviceElement) { + serviceElements.add(serviceElement); + } + + public void addSCAReferenceElement(SpringSCAReferenceElement referenceElement) { + referenceElements.add(referenceElement); + } + + public synchronized List<SpringBeanElement> getBeanElements() { + if (beanElements == null) { + beanElements = new ArrayList<SpringBeanElement>(); + for (String name : getBeanDefinitionNames()) { + BeanDefinition def = getBeanDefinition(name); + SpringBeanElement beanElement = new SpringBeanElement(name, def.getBeanClassName()); + beanElements.add(beanElement); + beanElement.setAbstractBean(def.isAbstract()); + beanElement.setFactoryBeanAttribute(def.getFactoryBeanName() != null); + beanElement.setFactoryMethodAttribute(def.getFactoryMethodName() != null); + beanElement.setParentAttribute(def.getParentName() != null); + beanElement.setInnerBean(beanElement.getId() == null); + + ConstructorArgumentValues args = def.getConstructorArgumentValues(); + for (Map.Entry<Integer, ValueHolder> e: args.getIndexedArgumentValues().entrySet()) { + ValueHolder holder = e.getValue(); + SpringConstructorArgElement arg = new SpringConstructorArgElement(holder.getType()); + arg.setIndex(e.getKey()); + beanElement.addCustructorArgs(arg); + } + + MutablePropertyValues values = def.getPropertyValues(); + for (PropertyValue p : values.getPropertyValueList()) { + SpringPropertyElement propertyElement = new SpringPropertyElement(p.getName()); + Object value = p.getValue(); + configurePropertyElement(propertyElement, value); + beanElement.getProperties().add(propertyElement); + } + } + } + return beanElements; + } + + public void configurePropertyElement(SpringPropertyElement propertyElement, Object value) { + if (value instanceof BeanReference) { + BeanReference beanRef = (BeanReference)value; + propertyElement.addRef(beanRef.getBeanName()); + } else if (value instanceof Collection) { + Collection collection = (Collection)value; + for (Object item : collection) { + configurePropertyElement(propertyElement, item); + } + } else if (value instanceof TypedStringValue) { + TypedStringValue stringValue = (TypedStringValue)value; + propertyElement.addValue(stringValue.getValue()); + } else { + if (value != null) { + propertyElement.addValue(value.toString()); + } + } + } + + public List<SpringSCAPropertyElement> getPropertyElements() { + return propertyElements; + } + + public List<SpringSCAServiceElement> getServiceElements() { + return serviceElements; + } + + public List<SpringSCAReferenceElement> getReferenceElements() { + return referenceElements; + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/context/SCAParentApplicationContext.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/context/SCAParentApplicationContext.java new file mode 100644 index 0000000000..cd81facc3d --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/context/SCAParentApplicationContext.java @@ -0,0 +1,213 @@ +/* + * 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.tuscany.sca.implementation.spring.context; + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.util.Locale; +import java.util.Map; + +import org.apache.tuscany.sca.implementation.spring.provider.SpringImplementationWrapper; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.config.AutowireCapableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.MessageSourceResolvable; +import org.springframework.context.NoSuchMessageException; +import org.springframework.core.io.Resource; + +/** + * A Spring ParentApplicationContext for a given Spring Implementation + * + * The Parent application context is responsible for handling those entities within a Spring + * application context that actually belong to SCA rather than to Spring. The principal things + * are Properties and References. These may be present either through explicit <sca:property/> + * and <sca:reference/> elements in the application context or they may be implicit through + * unresolved Spring bean <property.../> elements. In either case, it is the Parent application + * context that must provide Spring beans that correspond to the property or reference, as derived + * from the SCA composite in which the Spring application context is an implementation. + * + * @version $Rev$ $Date$ + */ +public class SCAParentApplicationContext implements ApplicationContext { + + // The Spring implementation for which this is the parent application context + private SpringImplementationWrapper implementation; + + private static final String[] EMPTY_ARRAY = new String[0]; + + public SCAParentApplicationContext(SpringImplementationWrapper implementation) { + this.implementation = implementation; + } // end constructor + + public Object getBean(String name) throws BeansException { + return getBean(name, (Class)null); + } + + /** + * Get a Bean for a reference or for a property. + * + * @param name - the name of the Bean required + * @param requiredType - the required type of the Bean (either a Java class or a Java interface) + * @return Object - a Bean which matches the requested bean + */ + public Object getBean(String name, Class requiredType) throws BeansException { + Object bean = implementation.getBean(name, requiredType); + if (bean == null && getParent() != null) { + bean = getParent().getBean(name, requiredType); + } + if (bean == null) { + throw new NoSuchBeanDefinitionException("Unable to find Bean with name " + name); + } else { + return bean; + } + } // end method getBean( String, Class ) + + public Object getBean(String name, Object[] args) throws BeansException { + return getBean(name, ((Class)null)); + } + + public <T> T getBean(Class<T> clazz) throws BeansException { + return clazz.cast(getBean(clazz.getName(), clazz)); + } + + public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> clazz) throws BeansException { + return null; + } + + public <A extends Annotation> A findAnnotationOnBean(String arg0, Class<A> clazz) { + return null; + } + + public boolean containsBean(String name) { + // TODO + return false; + } + + public boolean isSingleton(String name) throws NoSuchBeanDefinitionException { + // TODO + return false; + } + + public boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException { + throw new UnsupportedOperationException(); + } + + public Class getType(String name) throws NoSuchBeanDefinitionException { + return null; + } + + public String[] getAliases(String name) throws NoSuchBeanDefinitionException { + return EMPTY_ARRAY; + } + + public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException { + return null; + } + + public String getId() { + return this.toString(); + } + + public String getDisplayName() { + return implementation.getURI(); + } + + public long getStartupDate() { + return 0; + } + + public boolean containsBeanDefinition(String beanName) { + return false; + } + + public int getBeanDefinitionCount() { + return 0; + } + + public String[] getBeanDefinitionNames() { + return new String[0]; + } + + public String[] getBeanNamesForType(Class type) { + return new String[0]; + } + + public String[] getBeanNamesForType(Class type, boolean includePrototypes, boolean includeFactoryBeans) { + return new String[0]; + } + + public Map getBeansOfType(Class type) throws BeansException { + return null; + } + + public Map getBeansOfType(Class type, boolean includePrototypes, boolean includeFactoryBeans) throws BeansException { + return null; + } + + public boolean isPrototype(String theString) { + return false; + } + + public BeanFactory getParentBeanFactory() { + return null; + } + + public boolean containsLocalBean(String name) { + return false; + } + + public String getMessage(String code, Object[] args, String defaultMessage, Locale locale) { + return null; + } + + public String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException { + return null; + } + + public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException { + return null; + } + + public void publishEvent(ApplicationEvent event) { + + } + + public Resource[] getResources(String locationPattern) throws IOException { + return new Resource[0]; + } + + public Resource getResource(String location) { + return null; + } + + public ClassLoader getClassLoader() { + // REVIEW: this is almost certainly flawed, but it's not clear how the SCA runtime's + // resource loading mechanism is exposed right now. + return this.getClass().getClassLoader(); + } + + @Override + public ApplicationContext getParent() { + return implementation.getParentApplicationContext(); + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/context/SpringApplicationContextAccessor.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/context/SpringApplicationContextAccessor.java new file mode 100644 index 0000000000..2d18b5aa6c --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/context/SpringApplicationContextAccessor.java @@ -0,0 +1,41 @@ +/* + * 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.tuscany.sca.implementation.spring.context; + +import org.springframework.context.ApplicationContext; + +/** + * A utility to receive the parent Spring application context + */ +public interface SpringApplicationContextAccessor { + /** + * Get the parent Spring application context for the hosting environment. This will be used as the parent + * application context for implementation.spring components + * @return The parent application context + */ + ApplicationContext getParentApplicationContext(); + + /** + * Set the root Spring application context. This is particually useful for Spring web integration where Spring + * creates WebApplicationContext and keeps it in the ServletContext + * @param parentApplicationContext The parent application context + */ + void setParentApplicationContext(ApplicationContext parentApplicationContext); +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/context/SpringContextWrapper.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/context/SpringContextWrapper.java new file mode 100644 index 0000000000..4b0ad72972 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/context/SpringContextWrapper.java @@ -0,0 +1,130 @@ +/* + * 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.tuscany.sca.implementation.spring.context; + +import java.net.URL; +import java.util.List; + +import org.apache.tuscany.sca.implementation.spring.processor.ComponentNameAnnotationProcessor; +import org.apache.tuscany.sca.implementation.spring.processor.ConstructorAnnotationProcessor; +import org.apache.tuscany.sca.implementation.spring.processor.InitDestroyAnnotationProcessor; +import org.apache.tuscany.sca.implementation.spring.processor.PropertyAnnotationProcessor; +import org.apache.tuscany.sca.implementation.spring.processor.ReferenceAnnotationProcessor; +import org.apache.tuscany.sca.implementation.spring.provider.ComponentWrapper; +import org.apache.tuscany.sca.implementation.spring.provider.PropertyValueWrapper; +import org.apache.tuscany.sca.implementation.spring.provider.SpringImplementationWrapper; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.core.io.UrlResource; + +/** + * This is the runtime side tie for the corresponding tuscany side stub class. + * It enables the Tuscany code to invoke methods on a Spring context without + * needing to know about any Spring classes. See the SpringContextStub class + * in the implementation-spring module for what the stub does. + */ +public class SpringContextWrapper { + + private GenericApplicationContext springContext; + private SpringImplementationWrapper implementation; + + public SpringContextWrapper(SpringImplementationWrapper implementation, List<URL> resource) { + this.implementation = implementation; + SCAParentApplicationContext scaParentContext = new SCAParentApplicationContext(implementation); + springContext = createApplicationContext(scaParentContext, resource); + } + + public ApplicationContext getApplicationContext() { + return springContext; + } + + public void start() { + // Do refresh here to ensure that Spring Beans are not touched before the SCA config process is complete... + springContext.refresh(); + springContext.start(); + } + + public void close() { + springContext.close(); + if (springContext instanceof GenericApplicationContext) { + springContext.stop(); + } + } + + /** + * Include BeanPostProcessor to deal with SCA Annotations in Spring Bean + */ + private GenericApplicationContext createApplicationContext(SCAParentApplicationContext scaParentContext, + List<URL> resources) { + + GenericApplicationContext appCtx = + new SCAGenericApplicationContext(scaParentContext, implementation.getClassLoader()); + XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(appCtx); + + // REVIEW: [rfeng] How do we control the schema validation + xmlReader.setValidating(false); + + for (URL resource : resources) { + xmlReader.loadBeanDefinitions(new UrlResource(resource)); + } + xmlReader.setBeanClassLoader(implementation.getClassLoader()); + includeAnnotationProcessors(appCtx.getBeanFactory()); + return appCtx; + + } + + public Object getBean(String id) throws BeansException { + return springContext.getBean(id); + } + + /** + * Include BeanPostProcessor to deal with SCA Annotations in Spring Bean + */ + private void includeAnnotationProcessors(ConfigurableListableBeanFactory beanFactory) { + + // Processor to deal with @Init and @Destroy SCA Annotations + BeanPostProcessor initDestroyProcessor = new InitDestroyAnnotationProcessor(); + beanFactory.addBeanPostProcessor(initDestroyProcessor); + + // Processor to deal with @Reference SCA Annotations + ComponentWrapper component = implementation.getComponentWrapper(); + BeanPostProcessor referenceProcessor = new ReferenceAnnotationProcessor(component); + beanFactory.addBeanPostProcessor(referenceProcessor); + + // Processor to deal with @Property SCA Annotations + PropertyValueWrapper pvs = implementation.getPropertyValueWrapper(); + BeanPostProcessor propertyProcessor = new PropertyAnnotationProcessor(pvs); + beanFactory.addBeanPostProcessor(propertyProcessor); + + // Processor to deal with @ComponentName SCA Annotations + BeanPostProcessor componentNameProcessor = + new ComponentNameAnnotationProcessor(implementation.getComponentName()); + beanFactory.addBeanPostProcessor(componentNameProcessor); + + // Processor to deal with @Constructor SCA Annotations + BeanPostProcessor constructorProcessor = new ConstructorAnnotationProcessor(); + beanFactory.addBeanPostProcessor(constructorProcessor); + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/SCANamespaceHandlerResolver.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/SCANamespaceHandlerResolver.java new file mode 100644 index 0000000000..75e00007f6 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/SCANamespaceHandlerResolver.java @@ -0,0 +1,53 @@ +/* + * 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.tuscany.sca.implementation.spring.namespace; + +import org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver; +import org.springframework.beans.factory.xml.NamespaceHandler; + +/** + * Overrides the default Spring namespace resolver to automatically register + * {@link ScaNamespaceHandler} instead of requiring a value to be supplied in a + * Spring configuration + * + * @version $Rev$ $Date$ + */ +public class SCANamespaceHandlerResolver extends DefaultNamespaceHandlerResolver { + private static final String SCA_NAMESPACE = "http://www.springframework.org/schema/sca"; + + private ScaNamespaceHandler handler; + + public SCANamespaceHandlerResolver(ClassLoader classLoader) { + super(classLoader); + handler = new ScaNamespaceHandler(/*componentType*/); + } + + public SCANamespaceHandlerResolver(String handlerMappingsLocation, ClassLoader classLoader) { + super(classLoader, handlerMappingsLocation); + handler = new ScaNamespaceHandler(/*componentType*/); + } + + @Override + public NamespaceHandler resolve(String namespaceUri) { + if (SCA_NAMESPACE.equals(namespaceUri)) { + return handler; + } + return super.resolve(namespaceUri); + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/ScaNamespaceHandler.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/ScaNamespaceHandler.java new file mode 100644 index 0000000000..89c87ad1d1 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/ScaNamespaceHandler.java @@ -0,0 +1,38 @@ +/* + * Copyright 2002-2006 the original author or authors. + * + * Licensed 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.tuscany.sca.implementation.spring.namespace; + +import org.springframework.beans.factory.xml.NamespaceHandlerSupport; + +/** + * Handler for the <sca:> namespace in an application context + * + * @version $Rev$ $Date$ + */ +public class ScaNamespaceHandler extends NamespaceHandlerSupport { + + public ScaNamespaceHandler() { + } + + @Override + public void init() { + registerBeanDefinitionParser("reference", new ScaReferenceBeanDefinitionParser()); + registerBeanDefinitionParser("service", new ScaServiceBeanDefinitionParser()); + registerBeanDefinitionParser("property", new ScaPropertyBeanDefinitionParser()); + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/ScaPropertyBeanDefinitionParser.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/ScaPropertyBeanDefinitionParser.java new file mode 100644 index 0000000000..bff0aa84e0 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/ScaPropertyBeanDefinitionParser.java @@ -0,0 +1,44 @@ +/* + * Copyright 2002-2006 the original author or authors. + * + * Licensed 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.tuscany.sca.implementation.spring.namespace; + +import org.apache.tuscany.sca.implementation.spring.SpringSCAPropertyElement; +import org.apache.tuscany.sca.implementation.spring.context.SCAGenericApplicationContext; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.xml.BeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.w3c.dom.Element; + +/** + * Parser for the <sca:reference> element + * @version $Rev$ $Date$ + */ +public class ScaPropertyBeanDefinitionParser implements BeanDefinitionParser { + + public BeanDefinition parse(Element element, ParserContext parserContext) { + BeanDefinitionRegistry registry = parserContext.getRegistry(); + if (registry instanceof SCAGenericApplicationContext) { + SCAGenericApplicationContext context = (SCAGenericApplicationContext)registry; + SpringSCAPropertyElement propertyElement = + new SpringSCAPropertyElement(element.getAttributeNS(null, "name"), element.getAttributeNS(null, "type")); + context.addSCAPropertyElement(propertyElement); + } + // do nothing, this is handled by Tuscany + return null; + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/ScaReferenceBeanDefinitionParser.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/ScaReferenceBeanDefinitionParser.java new file mode 100644 index 0000000000..6cb4978a47 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/ScaReferenceBeanDefinitionParser.java @@ -0,0 +1,49 @@ +/* + * Copyright 2002-2006 the original author or authors. + * + * Licensed 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.tuscany.sca.implementation.spring.namespace; + +import org.apache.tuscany.sca.implementation.spring.SpringSCAReferenceElement; +import org.apache.tuscany.sca.implementation.spring.context.SCAGenericApplicationContext; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.xml.BeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.w3c.dom.Element; + +/** + * Parser for the <sca:reference> element + * + * @version $Rev$ $Date$ + */ +public class ScaReferenceBeanDefinitionParser implements BeanDefinitionParser { + + public BeanDefinition parse(Element element, ParserContext parserContext) { + BeanDefinitionRegistry registry = parserContext.getRegistry(); + if (registry instanceof SCAGenericApplicationContext) { + SCAGenericApplicationContext context = (SCAGenericApplicationContext)registry; + SpringSCAReferenceElement referenceElement = + new SpringSCAReferenceElement(element.getAttributeNS(null, "name"), + element.getAttributeNS(null, "type")); + referenceElement.setDefaultBean(element.getAttributeNS(null, "default")); + context.addSCAReferenceElement(referenceElement); + } + + // do nothing, this is handled by Tuscany + return null; + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/ScaServiceBeanDefinitionParser.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/ScaServiceBeanDefinitionParser.java new file mode 100644 index 0000000000..e5eabd2a4b --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/ScaServiceBeanDefinitionParser.java @@ -0,0 +1,48 @@ +/* + * Copyright 2002-2006 the original author or authors. + * + * Licensed 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.tuscany.sca.implementation.spring.namespace; + +import org.apache.tuscany.sca.implementation.spring.SpringSCAServiceElement; +import org.apache.tuscany.sca.implementation.spring.context.SCAGenericApplicationContext; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.xml.BeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.w3c.dom.Element; + +/** + * Parser for the <sca:service/> element + * + * @version $Rev$ $Date$ + */ +public class ScaServiceBeanDefinitionParser implements BeanDefinitionParser { + + public BeanDefinition parse(Element element, ParserContext parserContext) { + BeanDefinitionRegistry registry = parserContext.getRegistry(); + if (registry instanceof SCAGenericApplicationContext) { + SCAGenericApplicationContext context = (SCAGenericApplicationContext)registry; + SpringSCAServiceElement serviceElement = + new SpringSCAServiceElement(element.getAttributeNS(null, "name"), + element.getAttributeNS(null, "target")); + serviceElement.setType(element.getAttributeNS(null, "type")); + context.addSCAServiceElement(serviceElement); + } + // do nothing, handled by Tuscany + return null; + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ComponentNameAnnotationProcessor.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ComponentNameAnnotationProcessor.java new file mode 100644 index 0000000000..68d49bbc24 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ComponentNameAnnotationProcessor.java @@ -0,0 +1,151 @@ +/* + * 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.tuscany.sca.implementation.spring.processor; + +import java.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; +import java.lang.ref.Reference; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import org.oasisopen.sca.annotation.ComponentName; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.FatalBeanException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.util.Assert; +import org.springframework.util.ReflectionUtils; + +public class ComponentNameAnnotationProcessor implements BeanPostProcessor { + + private Class<? extends Annotation> componentNameAnnotationType = ComponentName.class; + + private String componentName; + + public ComponentNameAnnotationProcessor(String componentName) { + this.componentName = componentName; + } + + /** + * Gets componentName annotation type. + */ + protected Class<? extends Annotation> getComponentNameAnnotationType() { + return this.componentNameAnnotationType; + } + + /** + * Sets componentName annotation type. + */ + public void setComponentNameAnnotationType(Class<? extends Annotation> componentNameAnnotationType) { + Assert.notNull(componentNameAnnotationType, "'componentNameAnnotationType' type must not be null."); + this.componentNameAnnotationType = componentNameAnnotationType; + } + + /** + * This method is used to execute before a bean's initialization callback. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String) + */ + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + processAnnotation(bean); + return bean; + } + + /** + * This method is used to execute after a bean's initialization callback. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String) + */ + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + /** + * <p>Processes a beans fields for injection if it has a {@link Reference} annotation.</p> + */ + protected void processAnnotation(final Object bean) { + + final Class<?> clazz = bean.getClass(); + + ReflectionUtils.doWithFields(clazz, new ReflectionUtils.FieldCallback() { + public void doWith(Field field) { + Annotation annotation = field.getAnnotation(getComponentNameAnnotationType()); + + if (annotation != null) { + if (Modifier.isStatic(field.getModifiers())) { + throw new IllegalStateException("ComponentName annotation is not supported on static fields"); + } + + if (Modifier.isPrivate(field.getModifiers())) { + throw new IllegalStateException("ComponentName annotation is not supported on private fields"); + } + + ReflectionUtils.makeAccessible(field); + + if (field.getType().getName().equals("java.lang.String")) { + Object nameObj = componentName; + if (nameObj != null) + ReflectionUtils.setField(field, bean, nameObj); + } else { + throw new IllegalStateException( + "ComponentName annotation is supported only on java.lang.String field type."); + } + } + } + }); + + ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() { + public void doWith(Method method) { + Annotation annotation = method.getAnnotation(getComponentNameAnnotationType()); + + if (annotation != null) { + if (Modifier.isStatic(method.getModifiers())) { + throw new IllegalStateException("ComponentName annotation is not supported on static methods"); + } + + if (Modifier.isPrivate(method.getModifiers())) { + throw new IllegalStateException("ComponentName annotation is not supported on private methods"); + } + + if (method.getParameterTypes().length == 0) { + throw new IllegalStateException( + "ComponentName annotation requires at least one argument: " + method); + } + + PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method); + + if (pd.getPropertyType().getName().equals("java.lang.String")) { + Object nameObj = componentName; + if (nameObj != null) { + try { + pd.getWriteMethod().invoke(bean, new Object[] {nameObj}); + } catch (Throwable e) { + throw new FatalBeanException("Problem injecting reference: " + e.getMessage(), e); + } + } + } else { + throw new IllegalStateException( + "ComponentName annotation is supported only on java.lang.String field type."); + } + } + } + }); + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ConstructorAnnotationProcessor.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ConstructorAnnotationProcessor.java new file mode 100644 index 0000000000..a52a85ff3a --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ConstructorAnnotationProcessor.java @@ -0,0 +1,112 @@ +/* + * 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.tuscany.sca.implementation.spring.processor; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter; +import org.springframework.util.Assert; + +public class ConstructorAnnotationProcessor extends InstantiationAwareBeanPostProcessorAdapter { + + private Class<? extends Annotation> constructorAnnotationType = org.oasisopen.sca.annotation.Constructor.class; + + private Class<? extends Annotation> autowiredAnnotationType = Autowired.class; + + public ConstructorAnnotationProcessor() { + // Default constructor. + } + + /** + * Set the 'autowired' annotation type, to be used on constructors, fields, + * setter methods and arbitrary config methods. + */ + public void setAutowiredAnnotationType(Class<? extends Annotation> autowiredAnnotationType) { + Assert.notNull(autowiredAnnotationType, "'autowiredAnnotationType' must not be null"); + this.autowiredAnnotationType = autowiredAnnotationType; + } + + /** + * Return the 'autowired' annotation type. + */ + protected Class<? extends Annotation> getAutowiredAnnotationType() { + return this.autowiredAnnotationType; + } + + /** + * Return the 'constructor' annotation type. + */ + protected Class<? extends Annotation> getConstructorAnnotationType() { + return this.constructorAnnotationType; + } + + /** + * Sets the 'constructor' annotation type. + */ + public void setConstructorAnnotationType(Class<? extends Annotation> constructorAnnotationType) { + Assert.notNull(constructorAnnotationType, "'constructorAnnotationType' type must not be null."); + this.constructorAnnotationType = constructorAnnotationType; + } + + /** + * This method is used to execute before a bean's initialization callback. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String) + */ + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + /** + * This method is used to execute after a bean's initialization callback. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String) + */ + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + public Constructor[] determineCandidateConstructors(Class beanClass, String beanName) throws BeansException { + /*Constructor[] declaredConstructors = beanClass.getDeclaredConstructors(); + Method[] declaredMethods = beanClass.getDeclaredMethods(); + List candidates = new ArrayList(declaredConstructors.length); + + for (int i = 0; i < declaredMethods.length; i++) { + Method method = declaredMethods[i]; + Annotation annotation = method.getAnnotation(getConstructorAnnotationType()); + if (annotation != null) { + if (Modifier.isStatic(method.getModifiers())) { + throw new IllegalStateException("Constructor annotation is not supported on static methods"); + } + + if (candidates.size() == 1) { + throw new IllegalStateException("Only one method is allowed to have constructor annotation in a bean: " + method); + } + + candidates.add(method); + } + } + + return (Constructor[]) candidates.toArray(new Constructor[candidates.size()]);*/ + return null; + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/InitDestroyAnnotationProcessor.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/InitDestroyAnnotationProcessor.java new file mode 100644 index 0000000000..477582b1d3 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/InitDestroyAnnotationProcessor.java @@ -0,0 +1,75 @@ +/* + * 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.tuscany.sca.implementation.spring.processor; + +import java.lang.annotation.Annotation; + +import org.oasisopen.sca.annotation.Destroy; +import org.oasisopen.sca.annotation.Init; +import org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor; + +public class InitDestroyAnnotationProcessor extends InitDestroyAnnotationBeanPostProcessor { + + private static final long serialVersionUID = 0; + + private Class<? extends Annotation> initAnnotationType = Init.class; + private Class<? extends Annotation> destroyAnnotationType = Destroy.class; + + /** + * Gets init annotation type. + */ + protected Class<? extends Annotation> getInitAnnotationType() { + return this.initAnnotationType; + } + + /** + * Sets init annotation type. + */ + /* + * public void setInitAnnotationType(Class<? extends Annotation> + * initAnnotationType) { Assert.notNull(initAnnotationType, + * "Init annotation type must not be null."); this.initAnnotationType = + * initAnnotationType; } + */ + + /** + * Gets destroy annotation type. + */ + protected Class<? extends Annotation> getDestroyAnnotationType() { + return this.destroyAnnotationType; + } + + /** + * Sets destroy annotation type. + */ + /* + * public void setDestroyAnnotationType(Class<? extends Annotation> + * destroyAnnotationType) { Assert.notNull(destroyAnnotationType, + * "Destroy annotation type must not be null."); this.destroyAnnotationType + * = destroyAnnotationType; } + */ + + public InitDestroyAnnotationProcessor() { + // Set the @Init annotation type + setInitAnnotationType(initAnnotationType); + + // Set the @Destroy annotation type + setDestroyAnnotationType(destroyAnnotationType); + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/PropertyAnnotationProcessor.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/PropertyAnnotationProcessor.java new file mode 100644 index 0000000000..4763714a38 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/PropertyAnnotationProcessor.java @@ -0,0 +1,164 @@ +/* + * 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.tuscany.sca.implementation.spring.processor; + +import java.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import org.apache.tuscany.sca.implementation.spring.provider.PropertyValueWrapper; +import org.oasisopen.sca.annotation.Property; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.FatalBeanException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.util.Assert; +import org.springframework.util.ReflectionUtils; + +public class PropertyAnnotationProcessor implements BeanPostProcessor { + + private Class<? extends Annotation> propertyAnnotationType = Property.class; + + private PropertyValueWrapper propertyValue; + + public PropertyAnnotationProcessor(PropertyValueWrapper propertyValue) { + this.propertyValue = propertyValue; + } + + /** + * Gets property annotation type. + */ + protected Class<? extends Annotation> getPropertyAnnotationType() { + return this.propertyAnnotationType; + } + + /** + * Sets property annotation type. + */ + public void setPropertyAnnotationType(Class<? extends Annotation> propertyAnnotationType) { + Assert.notNull(propertyAnnotationType, "'propertyAnnotationType' type must not be null."); + this.propertyAnnotationType = propertyAnnotationType; + } + + /** + * This method is used to execute before a bean's initialization callback. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String) + */ + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + processAnnotation(bean); + return bean; + } + + /** + * This method is used to execute after a bean's initialization callback. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String) + */ + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + /** + * <p>Processes a beans fields for injection if it has a {@link Property} annotation.</p> + */ + protected void processAnnotation(final Object bean) { + + final Class<?> clazz = bean.getClass(); + + ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() { + public void doWith(Method method) { + + Property annotation = (Property)method.getAnnotation(getPropertyAnnotationType()); + + if (annotation != null) { + if (Modifier.isStatic(method.getModifiers())) { + throw new IllegalStateException("Property annotation is not supported on static methods"); + } + + /* + if (Modifier.isPrivate(method.getModifiers())) { + throw new IllegalStateException("Property annotation is not supported on private methods"); + } + */ + + if (method.getParameterTypes().length == 0) { + throw new IllegalStateException("Property annotation requires at least one argument: " + method); + } + + PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method); + if (pd != null) { + String propName = annotation.name(); + if ("".equals(propName)) { + injectProperty(bean, pd, propertyValue.getPropertyObj(pd.getPropertyType(), pd.getName())); + } else { + injectProperty(bean, pd, propertyValue.getPropertyObj(pd.getPropertyType(), propName)); + } + } + } + } + }); + + ReflectionUtils.doWithFields(clazz, new ReflectionUtils.FieldCallback() { + public void doWith(Field field) { + + Property annotation = (Property)field.getAnnotation(getPropertyAnnotationType()); + + if (annotation != null) { + if (Modifier.isStatic(field.getModifiers())) { + throw new IllegalStateException("Property annotation is not supported on static fields"); + } + + /* + if (Modifier.isPrivate(field.getModifiers())) { + throw new IllegalStateException("Property annotation is not supported on private fields"); + } + */ + + ReflectionUtils.makeAccessible(field); + + Object propertyObj = null; + String propName = annotation.name(); + if ("".equals(propName)) { + propertyObj = propertyValue.getPropertyObj(field.getType(), field.getName()); + } else { + propertyObj = propertyValue.getPropertyObj(field.getType(), propName); + } + + if (propertyObj != null) + ReflectionUtils.setField(field, bean, propertyObj); + } + } + }); + } + + public void injectProperty(Object bean, PropertyDescriptor pd, Object propertyObj) { + + if (propertyObj != null) { + try { + pd.getWriteMethod().invoke(bean, new Object[] {propertyObj}); + } catch (Throwable e) { + throw new FatalBeanException("Problem injecting property: " + e.getMessage(), e); + } + } + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ReferenceAnnotationProcessor.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ReferenceAnnotationProcessor.java new file mode 100644 index 0000000000..ad79db840e --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ReferenceAnnotationProcessor.java @@ -0,0 +1,168 @@ +/* + * 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.tuscany.sca.implementation.spring.processor; + +import java.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import org.apache.tuscany.sca.implementation.spring.provider.ComponentWrapper; +import org.oasisopen.sca.annotation.Reference; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.FatalBeanException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.util.Assert; +import org.springframework.util.ReflectionUtils; + +public class ReferenceAnnotationProcessor implements BeanPostProcessor { + + private Class<? extends Annotation> referenceAnnotationType = Reference.class; + private ComponentWrapper component; + + public ReferenceAnnotationProcessor(ComponentWrapper component) { + this.component = component; + } + + /** + * Gets referece annotation type. + */ + protected Class<? extends Annotation> getReferenceAnnotationType() { + return this.referenceAnnotationType; + } + + /** + * Sets referece annotation type. + */ + public void setReferenceAnnotationType(Class<? extends Annotation> referenceAnnotationType) { + Assert.notNull(referenceAnnotationType, "'referenceAnnotationType' type must not be null."); + this.referenceAnnotationType = referenceAnnotationType; + } + + /** + * This method is used to execute before a bean's initialization callback. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String) + */ + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + processAnnotation(bean); + return bean; + } + + /** + * This method is used to execute after a bean's initialization callback. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String) + */ + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + /** + * <p>Processes a beans fields for injection if it has a {@link Reference} annotation.</p> + */ + protected void processAnnotation(final Object bean) { + + final Class<?> clazz = bean.getClass(); + + ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() { + public void doWith(Method method) { + + Reference annotation = (Reference)method.getAnnotation(getReferenceAnnotationType()); + + if (annotation != null) { + if (Modifier.isStatic(method.getModifiers())) { + throw new IllegalStateException("Reference annotation is not supported on static methods"); + } + + /* + if (Modifier.isPrivate(method.getModifiers())) { + throw new IllegalStateException("Reference annotation is not supported on private methods"); + } + */ + + if (method.getParameterTypes().length == 0) { + throw new IllegalStateException( + "Reference annotation requires at least one argument: " + method); + } + + PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method); + if (pd != null) { + String refName = annotation.name(); + if ("".equals(refName)) { + injectReference(bean, pd, pd.getName()); + } else { + injectReference(bean, pd, refName); + } + } + } + } + }); + + ReflectionUtils.doWithFields(clazz, new ReflectionUtils.FieldCallback() { + public void doWith(Field field) { + + Reference annotation = (Reference)field.getAnnotation(getReferenceAnnotationType()); + + if (annotation != null) { + if (Modifier.isStatic(field.getModifiers())) { + throw new IllegalStateException("Reference annotation is not supported on static fields"); + } + + /* + if (Modifier.isPrivate(field.getModifiers())) { + throw new IllegalStateException("Reference annotation is not supported on private fields"); + } + */ + + ReflectionUtils.makeAccessible(field); + + Object referenceObj = null; + String refName = annotation.name(); + if ("".equals(refName)) { + referenceObj = component.getService(field.getType(), field.getName()); + } else { + referenceObj = component.getService(field.getType(), refName); + } + + if (referenceObj != null) + ReflectionUtils.setField(field, bean, referenceObj); + } + } + }); + } + + /** + * Processes a property descriptor to inject a service. + */ + public void injectReference(Object bean, PropertyDescriptor pd, String name) { + + Object referenceObj = component.getService(pd.getPropertyType(), name); + + if (referenceObj != null) { + try { + pd.getWriteMethod().invoke(bean, new Object[] {referenceObj}); + } catch (Throwable e) { + throw new FatalBeanException("Problem injecting reference: " + e.getMessage(), e); + } + } + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/SpringXMLBeanDefinitionLoaderImpl.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/SpringXMLBeanDefinitionLoaderImpl.java new file mode 100644 index 0000000000..71feddb9f5 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/SpringXMLBeanDefinitionLoaderImpl.java @@ -0,0 +1,78 @@ +/* + * 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.tuscany.sca.implementation.spring.processor; + +import java.net.URL; +import java.util.List; + +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.implementation.spring.SpringBeanElement; +import org.apache.tuscany.sca.implementation.spring.SpringSCAPropertyElement; +import org.apache.tuscany.sca.implementation.spring.SpringSCAReferenceElement; +import org.apache.tuscany.sca.implementation.spring.SpringSCAServiceElement; +import org.apache.tuscany.sca.implementation.spring.context.SCAGenericApplicationContext; +import org.apache.tuscany.sca.implementation.spring.xml.SpringXMLBeanDefinitionLoader; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; +import org.springframework.context.ApplicationContext; +import org.springframework.core.io.UrlResource; + +/** + * A tie that allows Tuscany to call Spring library to load the application context for the purpose of introspection + */ +public class SpringXMLBeanDefinitionLoaderImpl implements SpringXMLBeanDefinitionLoader { + + private static SCAGenericApplicationContext createApplicationContext(Object scaParentContext, + ClassLoader classLoader, + List<URL> resources) { + if (classLoader == null) { + classLoader = Thread.currentThread().getContextClassLoader(); + } + + SCAGenericApplicationContext appCtx = + new SCAGenericApplicationContext((ApplicationContext)scaParentContext, classLoader); + XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(appCtx); + + // REVIEW: [rfeng] How do we control the schema validation + xmlReader.setValidating(false); + + for (URL resource : resources) { + xmlReader.loadBeanDefinitions(new UrlResource(resource)); + } + + return appCtx; + + } + + @Override + public Object load(List<URL> resources, + List<SpringSCAServiceElement> serviceElements, + List<SpringSCAReferenceElement> referenceElements, + List<SpringSCAPropertyElement> propertyElements, + List<SpringBeanElement> beanElements, + ProcessorContext context) { + SCAGenericApplicationContext applicationContext = createApplicationContext(null, null, resources); + serviceElements.addAll(applicationContext.getServiceElements()); + referenceElements.addAll(applicationContext.getReferenceElements()); + propertyElements.addAll(applicationContext.getPropertyElements()); + beanElements.addAll(applicationContext.getBeanElements()); + return applicationContext; + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/ComponentWrapper.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/ComponentWrapper.java new file mode 100644 index 0000000000..5bddd8a006 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/ComponentWrapper.java @@ -0,0 +1,38 @@ +/* + * 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.tuscany.sca.implementation.spring.provider; + +/** + * Wrapper for the Component + */ +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +public class ComponentWrapper { + + private RuntimeComponent component; + + public ComponentWrapper(RuntimeComponent component) { + this.component = component; + } + + public Object getService(Class<?> type, String name) { + return component.getComponentContext().getService(type, name); + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/PropertyValueWrapper.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/PropertyValueWrapper.java new file mode 100644 index 0000000000..eca1492081 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/PropertyValueWrapper.java @@ -0,0 +1,50 @@ +/* + * 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.tuscany.sca.implementation.spring.provider; + +import java.util.List; + +import org.apache.tuscany.sca.assembly.ComponentProperty; +import org.apache.tuscany.sca.context.PropertyValueFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * Wrapper for PropertyValue + */ +public class PropertyValueWrapper { + + private RuntimeComponent component; + private PropertyValueFactory propertyFactory; + + public PropertyValueWrapper(RuntimeComponent component, PropertyValueFactory propertyFactory) { + this.component = component; + this.propertyFactory = propertyFactory; + } + + public Object getPropertyObj(Class<?> type, String name) { + List<ComponentProperty> props = component.getProperties(); + for (ComponentProperty prop : props) { + if (prop.getName().equals(name)) { + return propertyFactory.createPropertyValue(prop, type); + } + } + return null; // property name not found + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/SpringImplementationProvider.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/SpringImplementationProvider.java new file mode 100644 index 0000000000..db7831322a --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/SpringImplementationProvider.java @@ -0,0 +1,81 @@ +/* + * 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.tuscany.sca.implementation.spring.provider; + +import org.apache.tuscany.sca.context.PropertyValueFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.implementation.spring.context.SpringContextWrapper; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; +import org.springframework.context.ApplicationContext; + +/** + * A provider class for runtime Spring implementation instances + * @version $Rev$ $Date$ + */ +public class SpringImplementationProvider implements ImplementationProvider { + private RuntimeComponent component; + + // A Spring application context object + private SpringContextWrapper springContext; + + /** + * Constructor for the provider - takes a component definition and a Spring implementation + * description + * @param component - the component in the assembly + * @param implementation - the implementation + */ + public SpringImplementationProvider(RuntimeComponent component, + SpringImplementationWrapper implementation, + ApplicationContext parentApplicationContext, + ProxyFactory proxyService, + PropertyValueFactory propertyValueObjectFactory) { + super(); + this.component = component; + + springContext = new SpringContextWrapper(implementation, implementation.getResource()); + + } // end constructor + + public Invoker createInvoker(RuntimeComponentService service, Operation operation) { + return new SpringInvoker(component, springContext, service, operation); + } + + public boolean supportsOneWayInvocation() { + return false; + } + + /** + * Start this Spring implementation instance + */ + public void start() { + springContext.start(); + } + + /** + * Stop this implementation instance + */ + public void stop() { + springContext.close(); + } + +} // end class SpringImplementationProvider diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/SpringImplementationProviderFactory.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/SpringImplementationProviderFactory.java new file mode 100644 index 0000000000..be16fb3251 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/SpringImplementationProviderFactory.java @@ -0,0 +1,78 @@ +/* + * 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.tuscany.sca.implementation.spring.provider; + +import org.apache.tuscany.sca.context.PropertyValueFactory; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.core.invocation.ExtensibleProxyFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.implementation.spring.SpringImplementation; +import org.apache.tuscany.sca.implementation.spring.context.SpringApplicationContextAccessor; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.provider.ImplementationProviderFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.springframework.context.ApplicationContext; + +/** + * ImplementationProviderFactory for Spring implementation type + * @version $Rev$ $Date$ + * + */ +public class SpringImplementationProviderFactory implements ImplementationProviderFactory<SpringImplementation> { + private ProxyFactory proxyFactory; + private PropertyValueFactory propertyFactory; + private SpringApplicationContextAccessor contextAccessor; + + /** + * Simple constructor + * + */ + public SpringImplementationProviderFactory(ExtensionPointRegistry registry) { + super(); + UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class); + contextAccessor = utilities.getUtility(SpringApplicationContextAccessor.class); + proxyFactory = ExtensibleProxyFactory.getInstance(registry); + propertyFactory = utilities.getUtility(PropertyValueFactory.class); + } + + /** + * Returns a SpringImplementationProvider for a given component and Spring implementation + * @param component the component for which implementation instances are required + * @param implementation the Spring implementation with details of the component + * implementation + * @return the SpringImplementationProvider for the specified component + */ + public ImplementationProvider createImplementationProvider(RuntimeComponent component, + SpringImplementation implementation) { + ApplicationContext parentApplicationContext = + (contextAccessor != null) ? contextAccessor.getParentApplicationContext() : null; + SpringImplementationWrapper tie = + new SpringImplementationWrapper(implementation, parentApplicationContext, component, propertyFactory); + return new SpringImplementationProvider(component, tie, parentApplicationContext, proxyFactory, propertyFactory); + } + + /** + * Returns the class of the Spring implementation + */ + public Class<SpringImplementation> getModelType() { + return SpringImplementation.class; + } + +} // end class SpringImplementationProviderFactory diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/SpringImplementationWrapper.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/SpringImplementationWrapper.java new file mode 100644 index 0000000000..e5593f5eaa --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/SpringImplementationWrapper.java @@ -0,0 +1,158 @@ +/* + * 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.tuscany.sca.implementation.spring.provider; + +import java.net.URL; +import java.util.List; + +import org.apache.tuscany.sca.assembly.ComponentProperty; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.context.PropertyValueFactory; +import org.apache.tuscany.sca.implementation.spring.SpringImplementation; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.springframework.context.ApplicationContext; + +/** + * Wrapper for SpringImplementation + */ +public class SpringImplementationWrapper { + + private SpringImplementation implementation; + private ApplicationContext parentApplicationContext; + private RuntimeComponent component; + private PropertyValueFactory propertyFactory; + + public SpringImplementationWrapper(SpringImplementation implementation, + ApplicationContext parentApplicationContext, + RuntimeComponent component, + PropertyValueFactory propertyFactory) { + this.implementation = implementation; + this.component = component; + this.propertyFactory = propertyFactory; + this.parentApplicationContext = parentApplicationContext; + } + + public String getURI() { + return implementation.getURI(); + } + + public List<URL> getResource() { + return implementation.getResource(); + } + + public String getComponentName() { + return component.getName(); + } + + /** + * Method to create a Java Bean for a Property value + * @param <B> the class type of the Bean + * @param requiredType - a Class object for the required type + * @param name - the Property name + * @return - a Bean of the specified property, with value set + */ + private <B> B getPropertyBean(Class<?> requiredType, String name) { + B propertyObject = null; + // Get the component's list of properties + List<ComponentProperty> props = component.getProperties(); + for (ComponentProperty prop : props) { + if (prop.getName().equals(name)) { + // On finding the property, create a factory for it and create a Bean using + // the factory + propertyObject = (B)propertyFactory.createPropertyValue(prop, requiredType); + } // end if + } // end for + + return propertyObject; + } + + /** + * Creates a proxy Bean for a reference + * @param <B> the Business interface type for the reference + * @param businessInterface - the business interface as a Class + * @param referenceName - the name of the Reference + * @return an Bean of the type defined by <B> + */ + private <B> B getService(Class<B> businessInterface, String referenceName) { + return component.getComponentContext().getService(businessInterface, referenceName); + } + + /** + * Get a Bean for a reference or for a property. + * + * @param name - the name of the Bean required + * @param requiredType - the required type of the Bean (either a Java class or a Java interface) + * @return Object - a Bean which matches the requested bean + */ + public Object getBean(String name, Class<?> requiredType) { + // The expectation is that the requested Bean is either a reference or a property + // from the Spring context + for (Reference reference : implementation.getReferences()) { + if (reference.getName().equals(name)) { + // Extract the Java interface for the reference (it can't be any other interface type + // for a Spring application context) + if (requiredType == null) { + JavaInterface javaInterface = (JavaInterface)reference.getInterfaceContract().getInterface(); + requiredType = javaInterface.getJavaClass(); + } + // Create and return the proxy for the reference + return getService(requiredType, reference.getName()); + } // end if + } // end for + + // For a property, get the name and the required Java type and create a Bean + // of that type with the value inserted. + for (Property property : implementation.getProperties()) { + if (property.getName().equals(name)) { + if (requiredType == null) { + // The following code only deals with a subset of types and was superceded + // by the information from the implementation (which uses Classes as found + // in the Spring implementation itself. + //requiredType = JavaXMLMapper.getJavaType( property.getXSDType() ); + requiredType = implementation.getPropertyClass(name); + } + return getPropertyBean(requiredType, property.getName()); + } // end if + } // end for + // TODO: NoSuchBeanException + // throw new RuntimeException("Unable to find Bean with name " + name); + return null; + + } // end method getBean( String, Class ) + + public ComponentWrapper getComponentWrapper() { + return new ComponentWrapper(component); + } + + public PropertyValueWrapper getPropertyValueWrapper() { + return new PropertyValueWrapper(component, propertyFactory); + } + + public ClassLoader getClassLoader() { + return implementation.getClassLoader(); + } + + public ApplicationContext getParentApplicationContext() { + return parentApplicationContext; + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/SpringInvocationException.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/SpringInvocationException.java new file mode 100644 index 0000000000..0e1d3f5b5a --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/SpringInvocationException.java @@ -0,0 +1,40 @@ +/* + * 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.tuscany.sca.implementation.spring.provider; + +/** + * @version $Rev$ $Date$ + */ +public class SpringInvocationException extends Exception { + + private static final long serialVersionUID = -1157790036638157513L; + + public SpringInvocationException(String msg) { + super(msg); + } + + public SpringInvocationException(Throwable e) { + super(e); + } + + public SpringInvocationException(String msg, Throwable e) { + super(msg, e); + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/SpringInvoker.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/SpringInvoker.java new file mode 100644 index 0000000000..ea1d6e6755 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/SpringInvoker.java @@ -0,0 +1,126 @@ +/* + * 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.tuscany.sca.implementation.spring.provider; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.implementation.spring.SpringBeanElement; +import org.apache.tuscany.sca.implementation.spring.SpringImplementation; +import org.apache.tuscany.sca.implementation.spring.context.SpringContextWrapper; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceUtil; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; + +/** + * Initial implementation of a Spring bean invoker + * @version $Rev$ $Date$ + */ +public class SpringInvoker implements Invoker { + + private Method theMethod = null; + private Object bean; + private SpringBeanElement beanElement; + private boolean badInvoker = false; + + private SpringContextWrapper springContext; + private Operation operation; + + /** + * SpringInvoker constructor + * @param component - the Spring component to invoke + * @param service - the service to invoke + * @param operation - the operation to invoke + */ + public SpringInvoker(RuntimeComponent component, + SpringContextWrapper springContext, + RuntimeComponentService service, + Operation operation) { + + this.springContext = springContext; + this.operation = operation; + + // From the component and the service, identify the Spring Bean which is the target + SpringImplementation theImplementation = (SpringImplementation)component.getImplementation(); + beanElement = theImplementation.getBeanFromService(service.getService()); + + if (beanElement == null) { + badInvoker = true; + return; + } + + } // end constructor SpringInvoker + + // Lazy-load the method to avoid timing problems with the Spring Context + private void setupMethod() throws SpringInvocationException { + try { + bean = springContext.getBean(beanElement.getId()); + Class<?> beanClass = bean.getClass(); + theMethod = JavaInterfaceUtil.findMethod(beanClass, operation); + //System.out.println("SpringInvoker - found method " + theMethod.getName() ); + } catch (NoSuchMethodException e) { + throw new SpringInvocationException(e); + } + } + + private Object doInvoke(Object payload) throws SpringInvocationException { + if (theMethod == null) + setupMethod(); + + if (badInvoker) + throw new SpringInvocationException("Spring invoker incorrectly configured"); + // Invoke the method on the Spring bean using the payload, returning the results + try { + Object ret; + + if (payload != null && !payload.getClass().isArray()) { + ret = theMethod.invoke(bean, payload); + } else { + ret = theMethod.invoke(bean, (Object[])payload); + } + return ret; + } catch (InvocationTargetException e) { + throw new SpringInvocationException("Spring invoker invoke method '" + theMethod.getName() + "' error.", + e.getCause()); + } catch (Exception e) { + throw new SpringInvocationException("Spring invoker invoke method '" + theMethod.getName() + "' error.", e); + } + + } // end method doInvoke + + /** + * @param msg the message to invoke on the target bean + */ + public Message invoke(Message msg) { + try { + Object resp = doInvoke(msg.getBody()); + msg.setBody(resp); + } catch (SpringInvocationException e) { + msg.setFaultBody(e.getCause()); + } catch (Throwable e) { + msg.setFaultBody(e); + } + //System.out.println("Spring Invoker - invoke called"); + return msg; + } // end method invoke + +} // end class SpringInvoker diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.implementation.spring.xml.SpringXMLBeanDefinitionLoader b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.implementation.spring.xml.SpringXMLBeanDefinitionLoader new file mode 100644 index 0000000000..4c8fa09951 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.implementation.spring.xml.SpringXMLBeanDefinitionLoader @@ -0,0 +1,17 @@ +# 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. +org.apache.tuscany.sca.implementation.spring.processor.SpringXMLBeanDefinitionLoaderImpl;ranking=100
\ No newline at end of file diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ImplementationProviderFactory b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ImplementationProviderFactory new file mode 100644 index 0000000000..e6c8d70fe1 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ImplementationProviderFactory @@ -0,0 +1,20 @@ +# 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.
+
+# Implementation class for the implementation extension
+org.apache.tuscany.sca.implementation.spring.provider.SpringImplementationProviderFactory;model=org.apache.tuscany.sca.implementation.spring.SpringImplementation;ranking=100
+
diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/resources/META-INF/spring.handlers b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/resources/META-INF/spring.handlers new file mode 100644 index 0000000000..6d29e21024 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/resources/META-INF/spring.handlers @@ -0,0 +1 @@ +http\://www.springframework.org/schema/sca=org.apache.tuscany.sca.implementation.spring.namespace.ScaNamespaceHandler
diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/resources/META-INF/spring.schemas b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/resources/META-INF/spring.schemas new file mode 100644 index 0000000000..249cc21c13 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/resources/META-INF/spring.schemas @@ -0,0 +1 @@ +http\://www.osoa.org/xmlns/sca/1.0/spring-sca.xsd=org/springframework/sca/xml/spring-sca.xsd diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/resources/org/springframework/sca/xml/spring-sca.xsd b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/resources/org/springframework/sca/xml/spring-sca.xsd new file mode 100644 index 0000000000..dfa0b931f6 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-runtime/src/main/resources/org/springframework/sca/xml/spring-sca.xsd @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<xsd:schema xmlns="http://www.springframework.org/schema/sca" xmlns:xsd="http://www.w3.org/2001/XMLSchema" + attributeFormDefault="unqualified" elementFormDefault="qualified" + targetNamespace="http://www.springframework.org/schema/sca"> + + <xsd:element name="reference"> + <xsd:complexType> + <xsd:attribute name="name" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:string" /> + </xsd:simpleType> + </xsd:attribute> + <xsd:attribute name="type" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:string" /> + </xsd:simpleType> + </xsd:attribute> + <xsd:attribute name="default" use="optional"> + <xsd:simpleType> + <xsd:restriction base="xsd:string" /> + </xsd:simpleType> + </xsd:attribute> + </xsd:complexType> + </xsd:element> + + <xsd:element name="property"> + <xsd:complexType> + <xsd:attribute name="id" use="optional"> + <xsd:simpleType> + <xsd:restriction base="xsd:string" /> + </xsd:simpleType> + </xsd:attribute> + <xsd:attribute name="name" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:string" /> + </xsd:simpleType> + </xsd:attribute> + <xsd:attribute name="type" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:string" /> + </xsd:simpleType> + </xsd:attribute> + </xsd:complexType> + </xsd:element> + + <xsd:element name="service"> + <xsd:complexType> + <xsd:attribute name="name" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:string" /> + </xsd:simpleType> + </xsd:attribute> + <xsd:attribute name="type" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:string" /> + </xsd:simpleType> + </xsd:attribute> + <xsd:attribute name="target" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:string" /> + </xsd:simpleType> + </xsd:attribute> + </xsd:complexType> + </xsd:element> + +</xsd:schema> diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/LICENSE b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/LICENSE new file mode 100644 index 0000000000..6e529a25c4 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/LICENSE @@ -0,0 +1,205 @@ +
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed 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.
+
+
+
diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/META-INF/MANIFEST.MF b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..a41644caa8 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/META-INF/MANIFEST.MF @@ -0,0 +1,25 @@ +Manifest-Version: 1.0
+SCA-Version: 1.1
+Bundle-Name: Apache Tuscany SCA Spring Implementation Model
+Bundle-Vendor: The Apache Software Foundation
+Bundle-Version: 2.0.0
+Bundle-ManifestVersion: 2
+Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
+Bundle-Description: Apache Tuscany SCA Spring Implementation Model
+Import-Package: org.apache.tuscany.sca.assembly;version="2.0.0",
+ org.apache.tuscany.sca.assembly.impl;version="2.0.0",
+ org.apache.tuscany.sca.context;version="2.0.0",
+ org.apache.tuscany.sca.contribution.processor;version="2.0.0",
+ org.apache.tuscany.sca.core;version="2.0.0",
+ org.apache.tuscany.sca.core.invocation;version="2.0.0",
+ org.apache.tuscany.sca.implementation.spring;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef.java;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef.java.impl;version="2.0.0",
+ org.apache.tuscany.sca.invocation;version="2.0.0",
+ org.apache.tuscany.sca.provider;version="2.0.0",
+ org.apache.tuscany.sca.runtime;version="2.0.0",
+ org.oasisopen.sca;version="2.0.0"
+Bundle-SymbolicName: org.apache.tuscany.sca.implementation.spring.stub
+Bundle-DocURL: http://www.apache.org/
+Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6 diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/NOTICE b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/NOTICE new file mode 100644 index 0000000000..1325efd8bf --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/NOTICE @@ -0,0 +1,6 @@ +${pom.name}
+Copyright (c) 2005 - 2008 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/README b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/README new file mode 100644 index 0000000000..e1b1f98fe0 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/README @@ -0,0 +1,9 @@ +Note that the implementation spring modules have a different structure from other extensions.
+
+The aim is to have the Tuscany runtime embedded in a container with the Tuscany classes hidden
+from user applications and the Spring jar's packaged with the application. That means that the
+Tuscany code has no visibilty of the Spring classes and visa-versa. To implement that the
+implementation-spring module has no dependencies on Spring and the implementation-spring-runtime
+module has no dependencies on Tuscany (other than the sca-api), and reflection is used to call
+methods between the modules.
+
diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/pom.xml b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/pom.xml new file mode 100644 index 0000000000..f459f1755c --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/pom.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<project> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-modules</artifactId> + <version>2.0-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>tuscany-implementation-spring-stub</artifactId> + <name>Apache Tuscany SCA Spring Implementation Runtime Stub</name> + + <dependencies> + + <!-- **************************************** --> + <!-- * * --> + <!-- * DONT ADD ANY SPRING DEPENDENCIES!!! * --> + <!-- * * --> + <!-- * See the README for details why not * --> + <!-- * * --> + <!-- * * --> + <!-- **************************************** --> + + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-implementation-spring</artifactId> + <version>2.0-SNAPSHOT</version> + </dependency> + + </dependencies> +</project> diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/stub/SpringXMLBeanDefinitionLoaderStub.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/stub/SpringXMLBeanDefinitionLoaderStub.java new file mode 100644 index 0000000000..f34dfb8ceb --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/stub/SpringXMLBeanDefinitionLoaderStub.java @@ -0,0 +1,92 @@ +/* + * 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.tuscany.sca.implementation.spring.processor.stub; + +import java.lang.reflect.Method; +import java.net.URL; +import java.util.Arrays; +import java.util.List; + +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.implementation.spring.SpringBeanElement; +import org.apache.tuscany.sca.implementation.spring.SpringSCAPropertyElement; +import org.apache.tuscany.sca.implementation.spring.SpringSCAReferenceElement; +import org.apache.tuscany.sca.implementation.spring.SpringSCAServiceElement; +import org.apache.tuscany.sca.implementation.spring.xml.SpringXMLBeanDefinitionLoader; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * This is the Tuscany side stub for the corresponding runtime tie class. + * It enables the Tuscany code to invoke methods on a Spring context without + * needing to know about any Spring classes. See the SpringContextTie class + * in the implementation-spring-runtime module for what the tie does. + */ +public class SpringXMLBeanDefinitionLoaderStub implements SpringXMLBeanDefinitionLoader { + private final static String TIE = "org.apache.tuscany.sca.implementation.spring.processor.tie.SpringXMLLoaderTie"; + + private static Method createApplicationContext; + + public SpringXMLBeanDefinitionLoaderStub() throws Exception { + synchronized (SpringXMLBeanDefinitionLoaderStub.class) { + if (createApplicationContext == null) { + Class<?> tieClass = Class.forName(TIE, false, Thread.currentThread().getContextClassLoader()); + createApplicationContext = + tieClass.getMethod("createApplicationContext", Object.class, ClassLoader.class, List.class); + } + } + } + + public Object createApplicationContext(Object scaParentContext, ClassLoader classLoader, List<URL> resources) + throws Exception { + return createApplicationContext.invoke(null, scaParentContext, classLoader, resources); + } + + public Object load(List<URL> resources, + List<SpringSCAServiceElement> serviceElements, + List<SpringSCAReferenceElement> referenceElements, + List<SpringSCAPropertyElement> propertyElements, + List<SpringBeanElement> beanElements, + ProcessorContext context) { + try { + Object appContext = + createApplicationContext(null, Thread.currentThread().getContextClassLoader(), resources); + Class<?> cls = appContext.getClass(); + Method method = cls.getMethod("getElements", Class.class); + SpringSCAServiceElement[] serviceArray = + (SpringSCAServiceElement[])method.invoke(appContext, SpringSCAServiceElement.class); + serviceElements.addAll(Arrays.asList(serviceArray)); + + SpringSCAReferenceElement[] referenceArray = + (SpringSCAReferenceElement[])method.invoke(appContext, SpringSCAReferenceElement.class); + referenceElements.addAll(Arrays.asList(referenceArray)); + + SpringSCAPropertyElement[] propertyArray = + (SpringSCAPropertyElement[])method.invoke(appContext, SpringSCAPropertyElement.class); + propertyElements.addAll(Arrays.asList(propertyArray)); + + SpringBeanElement[] beanArray = (SpringBeanElement[])method.invoke(appContext, SpringBeanElement.class); + beanElements.addAll(Arrays.asList(beanArray)); + + return appContext; + } catch (Throwable e) { + throw new ServiceRuntimeException(e); + } + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/ComponentTie.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/ComponentTie.java new file mode 100644 index 0000000000..882aa587e5 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/ComponentTie.java @@ -0,0 +1,41 @@ +/* + * 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.tuscany.sca.implementation.spring.provider.stub; + +/** + * This is the Tuscany side tie for the corresponding Spring runtime side stub class. + * It enables the Tuscany code to invoke methods on a Spring context without + * needing to know about any Spring classes. See the ComponentStub class + * in the implementation-spring-runtime module for what the stub does. + */ +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +public class ComponentTie { + + private RuntimeComponent component; + + public ComponentTie(RuntimeComponent component) { + this.component = component; + } + + public Object getService(Class<?> type, String name) { + return component.getComponentContext().getService(type, name); + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/PropertyValueTie.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/PropertyValueTie.java new file mode 100644 index 0000000000..5e0c5263c2 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/PropertyValueTie.java @@ -0,0 +1,53 @@ +/* + * 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.tuscany.sca.implementation.spring.provider.stub; + +import java.util.List; + +import org.apache.tuscany.sca.assembly.ComponentProperty; +import org.apache.tuscany.sca.context.PropertyValueFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * This is the Tuscany side tie for the corresponding Spring runtime side stub class. + * It enables the Tuscany code to invoke methods on a Spring context without + * needing to know about any Spring classes. See the PropertyValueStub class + * in the implementation-spring-runtime module for what the stub does. + */ +public class PropertyValueTie { + + private RuntimeComponent component; + private PropertyValueFactory propertyFactory; + + public PropertyValueTie(RuntimeComponent component, PropertyValueFactory propertyFactory) { + this.component = component; + this.propertyFactory = propertyFactory; + } + + public Object getPropertyObj(Class<?> type, String name) { + List<ComponentProperty> props = component.getProperties(); + for (ComponentProperty prop : props) { + if (prop.getName().equals(name)) { + return propertyFactory.createPropertyValue(prop, type); + } + } + return null; // property name not found + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/SpringApplicationContextAccessor.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/SpringApplicationContextAccessor.java new file mode 100644 index 0000000000..84a65bcf17 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/SpringApplicationContextAccessor.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.tuscany.sca.implementation.spring.provider.stub; + +/** + * A utility to receive the parent Spring application context + */ +public interface SpringApplicationContextAccessor { + /** + * Get the parent Spring application context for the hosting environment. This will be used as the parent + * application context for implementation.spring components + * @return The parent application context + */ + Object getParentApplicationContext(); + + /** + * Set the root Spring application context. This is particually useful for Spring web integration where Spring + * creates WebApplicationContext and keeps it in the ServletContext + * @param parentApplicationContext The parent application context + */ + void setParentApplicationContext(Object parentApplicationContext); +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/SpringContextStub.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/SpringContextStub.java new file mode 100644 index 0000000000..062da4b2d2 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/SpringContextStub.java @@ -0,0 +1,142 @@ +/* + * 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.tuscany.sca.implementation.spring.provider.stub; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.List; + +import org.apache.tuscany.sca.context.PropertyValueFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.implementation.spring.SpringImplementation; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * This is the Tuscany side stub for the corresponding runtime tie class. + * It enables the Tuscany code to invoke methods on a Spring context without + * needing to know about any Spring classes. See the SpringContextTie class + * in the implementation-spring-runtime module for what the tie does. + */ +public class SpringContextStub { + + private static final String SPRING_IMPLEMENTATION_STUB = + "org.apache.tuscany.sca.implementation.spring.context.tie.SpringImplementationStub"; + private static final String SPRING_CONTEXT_TIE = + "org.apache.tuscany.sca.implementation.spring.context.tie.SpringContextTie"; + private Object tie; + private Method startMethod; + private Method closeMethod; + private Method getBeanMethod; + + public SpringContextStub(RuntimeComponent component, + SpringImplementation implementation, + Object parentApplicationContext, + ProxyFactory proxyService, + PropertyValueFactory propertyValueObjectFactory) { + + initTie(component, implementation, parentApplicationContext, propertyValueObjectFactory); + + } + + private void initTie(RuntimeComponent component, + SpringImplementation implementation, + Object parentApplicationContext, + PropertyValueFactory propertyValueObjectFactory) { + + // TODO: what class loader to use? + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + + try { + + Class<?> stubClass = Class.forName(SPRING_IMPLEMENTATION_STUB, true, cl); + Constructor<?> stubConstructor = stubClass.getConstructor(new Class<?>[] {Object.class}); + Object stub = + stubConstructor.newInstance(new SpringImplementationTie(implementation, parentApplicationContext, + component, propertyValueObjectFactory)); + + Class<?> tieClass = Class.forName(SPRING_CONTEXT_TIE, true, cl); + Constructor<?> tieConstructor = tieClass.getConstructor(new Class<?>[] {stubClass, List.class}); + this.tie = tieConstructor.newInstance(stub, implementation.getResource()); + + this.startMethod = tieClass.getMethod("start"); + this.closeMethod = tieClass.getMethod("close"); + this.getBeanMethod = tieClass.getMethod("getBean", String.class); + + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } catch (SecurityException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (IllegalArgumentException e) { + throw new RuntimeException(e); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + public void start() { + try { + startMethod.invoke(tie); + } catch (IllegalArgumentException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + public void close() { + try { + closeMethod.invoke(tie); + } catch (IllegalArgumentException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + public Object getBean(String id) throws SpringInvocationException { + try { + + return getBeanMethod.invoke(tie, id); + + } catch (IllegalArgumentException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/SpringImplementationProvider.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/SpringImplementationProvider.java new file mode 100644 index 0000000000..e0207b9f12 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/SpringImplementationProvider.java @@ -0,0 +1,80 @@ +/* + * 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.tuscany.sca.implementation.spring.provider.stub; + +import org.apache.tuscany.sca.context.PropertyValueFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.implementation.spring.SpringImplementation; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; + +/** + * A provider class for runtime Spring implementation instances + * @version $Rev$ $Date$ + */ +public class SpringImplementationProvider implements ImplementationProvider { + private RuntimeComponent component; + + // A Spring application context object + private SpringContextStub springContext; + + /** + * Constructor for the provider - takes a component definition and a Spring implementation + * description + * @param component - the component in the assembly + * @param implementation - the implementation + */ + public SpringImplementationProvider(RuntimeComponent component, + SpringImplementation implementation, + Object parentApplicationContext, + ProxyFactory proxyService, + PropertyValueFactory propertyValueObjectFactory) { + super(); + this.component = component; + + springContext = new SpringContextStub(component, implementation, parentApplicationContext, proxyService, propertyValueObjectFactory); + + } // end constructor + + public Invoker createInvoker(RuntimeComponentService service, Operation operation) { + return new SpringInvoker(component, springContext, service, operation); + } + + public boolean supportsOneWayInvocation() { + return false; + } + + /** + * Start this Spring implementation instance + */ + public void start() { + springContext.start(); + } + + /** + * Stop this implementation instance + */ + public void stop() { + springContext.close(); + } + +} // end class SpringImplementationProvider diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/SpringImplementationProviderFactory.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/SpringImplementationProviderFactory.java new file mode 100644 index 0000000000..d402ff2eb6 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/SpringImplementationProviderFactory.java @@ -0,0 +1,75 @@ +/* + * 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.tuscany.sca.implementation.spring.provider.stub; + +import org.apache.tuscany.sca.context.PropertyValueFactory; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.core.invocation.ExtensibleProxyFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.implementation.spring.SpringImplementation; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.provider.ImplementationProviderFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * ImplementationProviderFactory for Spring implementation type + * @version $Rev$ $Date$ + * + */ +public class SpringImplementationProviderFactory implements ImplementationProviderFactory<SpringImplementation> { + private ProxyFactory proxyFactory; + private PropertyValueFactory propertyFactory; + private SpringApplicationContextAccessor contextAccessor; + + /** + * Simple constructor + * + */ + public SpringImplementationProviderFactory(ExtensionPointRegistry registry) { + super(); + UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class); + contextAccessor = utilities.getUtility(SpringApplicationContextAccessor.class); + proxyFactory = ExtensibleProxyFactory.getInstance(registry); + propertyFactory = utilities.getUtility(PropertyValueFactory.class); + } + + /** + * Returns a SpringImplementationProvider for a given component and Spring implementation + * @param component the component for which implementation instances are required + * @param implementation the Spring implementation with details of the component + * implementation + * @return the SpringImplementationProvider for the specified component + */ + public ImplementationProvider createImplementationProvider(RuntimeComponent component, + SpringImplementation implementation) { + Object parentApplicationContext = + (contextAccessor != null) ? contextAccessor.getParentApplicationContext() : null; + return new SpringImplementationProvider(component, implementation, parentApplicationContext, proxyFactory, + propertyFactory); + } + + /** + * Returns the class of the Spring implementation + */ + public Class<SpringImplementation> getModelType() { + return SpringImplementation.class; + } + +} // end class SpringImplementationProviderFactory diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/SpringImplementationTie.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/SpringImplementationTie.java new file mode 100644 index 0000000000..fc75faed21 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/SpringImplementationTie.java @@ -0,0 +1,156 @@ +/* + * 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.tuscany.sca.implementation.spring.provider.stub; + +import java.util.List; + +import org.apache.tuscany.sca.assembly.ComponentProperty; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.context.PropertyValueFactory; +import org.apache.tuscany.sca.implementation.spring.SpringImplementation; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * This is the Tuscany side tie for the corresponding runtime stub class. + * It enables the Sping code in the runtime module to invoke methods on a + * Tuscany SpringImplementation without the Spring runtime module + * needing to know about any Tuscany classes. See the SpringImplementationStub class + * in the implementation-spring-runtime module for what the stub does. + */ +public class SpringImplementationTie { + + private SpringImplementation implementation; + private Object parentApplicationContext; + private RuntimeComponent component; + private PropertyValueFactory propertyFactory; + + public SpringImplementationTie(SpringImplementation implementation, + Object parentApplicationContext, + RuntimeComponent component, + PropertyValueFactory propertyFactory) { + this.implementation = implementation; + this.component = component; + this.propertyFactory = propertyFactory; + this.parentApplicationContext = parentApplicationContext; + } + + public String getURI() { + return implementation.getURI(); + } + + public String getComponentName() { + return component.getName(); + } + + /** + * Method to create a Java Bean for a Property value + * @param <B> the class type of the Bean + * @param requiredType - a Class object for the required type + * @param name - the Property name + * @return - a Bean of the specified property, with value set + */ + private <B> B getPropertyBean(Class<?> requiredType, String name) { + B propertyObject = null; + // Get the component's list of properties + List<ComponentProperty> props = component.getProperties(); + for (ComponentProperty prop : props) { + if (prop.getName().equals(name)) { + // On finding the property, create a factory for it and create a Bean using + // the factory + propertyObject = (B) propertyFactory.createPropertyValue(prop, requiredType); + } // end if + } // end for + + return propertyObject; + } + + /** + * Creates a proxy Bean for a reference + * @param <B> the Business interface type for the reference + * @param businessInterface - the business interface as a Class + * @param referenceName - the name of the Reference + * @return an Bean of the type defined by <B> + */ + private <B> B getService(Class<B> businessInterface, String referenceName) { + return component.getComponentContext().getService(businessInterface, referenceName); + } + + /** + * Get a Bean for a reference or for a property. + * + * @param name - the name of the Bean required + * @param requiredType - the required type of the Bean (either a Java class or a Java interface) + * @return Object - a Bean which matches the requested bean + */ + public Object getBean(String name, Class<?> requiredType) { + // The expectation is that the requested Bean is either a reference or a property + // from the Spring context + for (Reference reference : implementation.getReferences()) { + if (reference.getName().equals(name)) { + // Extract the Java interface for the reference (it can't be any other interface type + // for a Spring application context) + if (requiredType == null) { + JavaInterface javaInterface = (JavaInterface)reference.getInterfaceContract().getInterface(); + requiredType = javaInterface.getJavaClass(); + } + // Create and return the proxy for the reference + return getService(requiredType, reference.getName()); + } // end if + } // end for + + // For a property, get the name and the required Java type and create a Bean + // of that type with the value inserted. + for (Property property : implementation.getProperties()) { + if (property.getName().equals(name)) { + if (requiredType == null) { + // The following code only deals with a subset of types and was superceded + // by the information from the implementation (which uses Classes as found + // in the Spring implementation itself. + //requiredType = JavaXMLMapper.getJavaType( property.getXSDType() ); + requiredType = implementation.getPropertyClass(name); + } + return getPropertyBean(requiredType, property.getName()); + } // end if + } // end for + // TODO: NoSuchBeanException + // throw new RuntimeException("Unable to find Bean with name " + name); + return null; + + } // end method getBean( String, Class ) + + public Object getComponentTie() { + return new ComponentTie(component); + } + + public Object getPropertyValueTie() { + return new PropertyValueTie(component, propertyFactory); + } + + public ClassLoader getClassLoader() { + return implementation.getClassLoader(); + } + + public Object getParentApplicationContext() { + return parentApplicationContext; + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/SpringInvocationException.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/SpringInvocationException.java new file mode 100644 index 0000000000..909a640563 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/SpringInvocationException.java @@ -0,0 +1,40 @@ +/* + * 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.tuscany.sca.implementation.spring.provider.stub; + +/** + * @version $Rev$ $Date$ + */ +public class SpringInvocationException extends Exception { + + private static final long serialVersionUID = -1157790036638157513L; + + public SpringInvocationException(String msg) { + super(msg); + } + + public SpringInvocationException(Throwable e) { + super(e); + } + + public SpringInvocationException(String msg, Throwable e) { + super(msg, e); + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/SpringInvoker.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/SpringInvoker.java new file mode 100644 index 0000000000..7d73eb5e6a --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/java/org/apache/tuscany/sca/implementation/spring/provider/stub/SpringInvoker.java @@ -0,0 +1,125 @@ +/* + * 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.tuscany.sca.implementation.spring.provider.stub; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.implementation.spring.SpringBeanElement; +import org.apache.tuscany.sca.implementation.spring.SpringImplementation; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceUtil; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; + +/** + * Initial implementation of a Spring bean invoker + * @version $Rev$ $Date$ + */ +public class SpringInvoker implements Invoker { + + private Method theMethod = null; + private Object bean; + private SpringBeanElement beanElement; + private boolean badInvoker = false; + + private SpringContextStub springContext; + private Operation operation; + + /** + * SpringInvoker constructor + * @param component - the Spring component to invoke + * @param service - the service to invoke + * @param operation - the operation to invoke + */ + public SpringInvoker(RuntimeComponent component, + SpringContextStub springContext, + RuntimeComponentService service, + Operation operation) { + + this.springContext = springContext; + this.operation = operation; + + // From the component and the service, identify the Spring Bean which is the target + SpringImplementation theImplementation = (SpringImplementation)component.getImplementation(); + beanElement = theImplementation.getBeanFromService(service.getService()); + + if (beanElement == null) { + badInvoker = true; + return; + } + + } // end constructor SpringInvoker + + // Lazy-load the method to avoid timing problems with the Spring Context + private void setupMethod() throws SpringInvocationException { + try { + bean = springContext.getBean(beanElement.getId()); + Class<?> beanClass = bean.getClass(); + theMethod = JavaInterfaceUtil.findMethod(beanClass, operation); + //System.out.println("SpringInvoker - found method " + theMethod.getName() ); + } catch (NoSuchMethodException e) { + throw new SpringInvocationException(e); + } + } + + private Object doInvoke(Object payload) throws SpringInvocationException { + if (theMethod == null) + setupMethod(); + + if (badInvoker) + throw new SpringInvocationException("Spring invoker incorrectly configured"); + // Invoke the method on the Spring bean using the payload, returning the results + try { + Object ret; + + if (payload != null && !payload.getClass().isArray()) { + ret = theMethod.invoke(bean, payload); + } else { + ret = theMethod.invoke(bean, (Object[])payload); + } + return ret; + } catch (InvocationTargetException e) { + throw new SpringInvocationException("Spring invoker invoke method '" + theMethod.getName() + "' error.", + e.getCause()); + } catch (Exception e) { + throw new SpringInvocationException("Spring invoker invoke method '" + theMethod.getName() + "' error.", e); + } + + } // end method doInvoke + + /** + * @param msg the message to invoke on the target bean + */ + public Message invoke(Message msg) { + try { + Object resp = doInvoke(msg.getBody()); + msg.setBody(resp); + } catch (SpringInvocationException e) { + msg.setFaultBody(e.getCause()); + } catch (Throwable e) { + msg.setFaultBody(e); + } + //System.out.println("Spring Invoker - invoke called"); + return msg; + } // end method invoke + +} // end class SpringInvoker diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/resources/META-INF/services/org.apache.tuscany.sca.implementation.spring.xml.SpringXMLBeanDefinitionLoader b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/resources/META-INF/services/org.apache.tuscany.sca.implementation.spring.xml.SpringXMLBeanDefinitionLoader new file mode 100644 index 0000000000..0a46baa13b --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/resources/META-INF/services/org.apache.tuscany.sca.implementation.spring.xml.SpringXMLBeanDefinitionLoader @@ -0,0 +1,17 @@ +# 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. +org.apache.tuscany.sca.implementation.spring.processor.stub.SpringXMLBeanDefinitionLoaderStub;ranking=50
\ No newline at end of file diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ImplementationProviderFactory b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ImplementationProviderFactory new file mode 100644 index 0000000000..e037ea60f5 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-stub/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ImplementationProviderFactory @@ -0,0 +1,20 @@ +# 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.
+
+# Implementation class for the implementation extension
+org.apache.tuscany.sca.implementation.spring.provider.stub.SpringImplementationProviderFactory;model=org.apache.tuscany.sca.implementation.spring.SpringImplementation;ranking=50
+
diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/LICENSE b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/LICENSE new file mode 100644 index 0000000000..6e529a25c4 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/LICENSE @@ -0,0 +1,205 @@ +
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed 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.
+
+
+
diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/META-INF/MANIFEST.MF b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..5d452244d2 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/META-INF/MANIFEST.MF @@ -0,0 +1,25 @@ +Manifest-Version: 1.0
+SCA-Version: 1.1
+Bundle-Name: Apache Tuscany SCA Spring Implementation Runtime Model
+Bundle-Vendor: The Apache Software Foundation
+Bundle-Version: 2.0.0
+Bundle-ManifestVersion: 2
+Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
+Bundle-Description: Apache Tuscany SCA Spring Implementation Runtime Model
+Bundle-SymbolicName: org.apache.tuscany.sca.implementation.spring.tie
+Bundle-DocURL: http://www.apache.org/
+Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6 +Import-Package: org.oasisopen.sca;version="2.0.0",
+ org.oasisopen.sca.annotation;version="2.0.0",
+ org.springframework.beans;version="3.0.2.RELEASE",
+ org.springframework.beans.factory;version="3.0.2.RELEASE",
+ org.springframework.beans.factory.annotation;version="3.0.2.RELEASE",
+ org.springframework.beans.factory.config;version="3.0.2.RELEASE",
+ org.springframework.beans.factory.support;version="3.0.2.RELEASE",
+ org.springframework.beans.factory.xml;version="3.0.2.RELEASE",
+ org.springframework.context;version="3.0.2.RELEASE",
+ org.springframework.context.support;version="3.0.2.RELEASE",
+ org.springframework.core;version="3.0.2.RELEASE",
+ org.springframework.core.io;version="3.0.2.RELEASE",
+ org.springframework.util;version="3.0.2.RELEASE"
+
diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/NOTICE b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/NOTICE new file mode 100644 index 0000000000..1325efd8bf --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/NOTICE @@ -0,0 +1,6 @@ +${pom.name}
+Copyright (c) 2005 - 2008 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/README b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/README new file mode 100644 index 0000000000..e1b1f98fe0 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/README @@ -0,0 +1,9 @@ +Note that the implementation spring modules have a different structure from other extensions.
+
+The aim is to have the Tuscany runtime embedded in a container with the Tuscany classes hidden
+from user applications and the Spring jar's packaged with the application. That means that the
+Tuscany code has no visibilty of the Spring classes and visa-versa. To implement that the
+implementation-spring module has no dependencies on Spring and the implementation-spring-runtime
+module has no dependencies on Tuscany (other than the sca-api), and reflection is used to call
+methods between the modules.
+
diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/pom.xml b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/pom.xml new file mode 100644 index 0000000000..a30109d442 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/pom.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<project> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-modules</artifactId> + <version>2.0-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>tuscany-implementation-spring-tie</artifactId> + <name>Apache Tuscany SCA Spring Implementation Runtime Tie</name> + + <dependencies> + + <!-- **************************************** --> + <!-- * * --> + <!-- * DONT ADD ANY TUSCANY DEPENDENCIES!!! * --> + <!-- * * --> + <!-- * See the README for details why not * --> + <!-- * * --> + <!-- * * --> + <!-- **************************************** --> + + <!-- SCA API dependency --> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-sca-api</artifactId> + <version>2.0-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + + <!-- Spring dependencies... --> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-core</artifactId> + <version>3.0.2.RELEASE</version> + </dependency> + + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-beans</artifactId> + <version>3.0.2.RELEASE</version> + </dependency> + + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-context</artifactId> + <version>3.0.2.RELEASE</version> + </dependency> + + </dependencies> +</project> diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/context/tie/SCAGenericApplicationContext.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/context/tie/SCAGenericApplicationContext.java new file mode 100644 index 0000000000..69e2ee2865 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/context/tie/SCAGenericApplicationContext.java @@ -0,0 +1,176 @@ +/* + * 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.tuscany.sca.implementation.spring.context.tie; + +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.implementation.spring.elements.tie.SpringBeanElement; +import org.apache.tuscany.sca.implementation.spring.elements.tie.SpringConstructorArgElement; +import org.apache.tuscany.sca.implementation.spring.elements.tie.SpringElementTie; +import org.apache.tuscany.sca.implementation.spring.elements.tie.SpringPropertyElement; +import org.apache.tuscany.sca.implementation.spring.elements.tie.SpringSCAPropertyElement; +import org.apache.tuscany.sca.implementation.spring.elements.tie.SpringSCAReferenceElement; +import org.apache.tuscany.sca.implementation.spring.elements.tie.SpringSCAServiceElement; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.beans.PropertyValue; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanReference; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.config.ConstructorArgumentValues; +import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder; +import org.springframework.beans.factory.config.TypedStringValue; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.GenericApplicationContext; + +public class SCAGenericApplicationContext extends GenericApplicationContext { + + private ClassLoader classloader = null; + private List<SpringSCAPropertyElement> propertyElements = new ArrayList<SpringSCAPropertyElement>(); + private List<SpringSCAServiceElement> serviceElements = new ArrayList<SpringSCAServiceElement>(); + private List<SpringSCAReferenceElement> referenceElements = new ArrayList<SpringSCAReferenceElement>(); + private List<SpringBeanElement> beanElements; + + public SCAGenericApplicationContext(DefaultListableBeanFactory beanFactory, + ApplicationContext parent, + ClassLoader classloader) { + super(beanFactory, parent); + this.classloader = classloader; + } + + public SCAGenericApplicationContext(ApplicationContext parent, ClassLoader classloader) { + super(parent); + this.classloader = classloader; + } + + @Override + protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { + beanFactory.setBeanClassLoader(classloader); + } + + public void addSCAPropertyElement(SpringSCAPropertyElement propertyElement) { + propertyElements.add(propertyElement); + } + + public void addSCAServiceElement(SpringSCAServiceElement serviceElement) { + serviceElements.add(serviceElement); + } + + public void addSCAReferenceElement(SpringSCAReferenceElement referenceElement) { + referenceElements.add(referenceElement); + } + + public synchronized List<SpringBeanElement> getBeanElements() { + if (beanElements == null) { + beanElements = new ArrayList<SpringBeanElement>(); + for (String name : getBeanDefinitionNames()) { + BeanDefinition def = getBeanDefinition(name); + SpringBeanElement beanElement = new SpringBeanElement(name, def.getBeanClassName()); + beanElements.add(beanElement); + beanElement.setAbstractBean(def.isAbstract()); + beanElement.setFactoryBeanAttribute(def.getFactoryBeanName() != null); + beanElement.setFactoryMethodAttribute(def.getFactoryMethodName() != null); + beanElement.setParentAttribute(def.getParentName() != null); + beanElement.setInnerBean(beanElement.getId() == null); + + ConstructorArgumentValues args = def.getConstructorArgumentValues(); + for (Map.Entry<Integer, ValueHolder> e: args.getIndexedArgumentValues().entrySet()) { + ValueHolder holder = e.getValue(); + SpringConstructorArgElement arg = new SpringConstructorArgElement(holder.getType()); + arg.setIndex(e.getKey()); + beanElement.addCustructorArgs(arg); + } + + MutablePropertyValues values = def.getPropertyValues(); + for (PropertyValue p : values.getPropertyValueList()) { + SpringPropertyElement propertyElement = new SpringPropertyElement(p.getName()); + Object value = p.getValue(); + configurePropertyElement(propertyElement, value); + beanElement.getProperties().add(propertyElement); + } + } + } + return beanElements; + } + + public void configurePropertyElement(SpringPropertyElement propertyElement, Object value) { + if (value instanceof BeanReference) { + BeanReference beanRef = (BeanReference)value; + propertyElement.addRef(beanRef.getBeanName()); + } else if (value instanceof Collection) { + Collection collection = (Collection)value; + for (Object item : collection) { + configurePropertyElement(propertyElement, item); + } + } else if (value instanceof TypedStringValue) { + TypedStringValue stringValue = (TypedStringValue)value; + propertyElement.addValue(stringValue.getValue()); + } else { + if (value != null) { + propertyElement.addValue(value.toString()); + } + } + } + + public List<SpringSCAPropertyElement> getPropertyElements() { + return propertyElements; + } + + public List<SpringSCAServiceElement> getServiceElements() { + return serviceElements; + } + + public List<SpringSCAReferenceElement> getReferenceElements() { + return referenceElements; + } + + public <T> T[] getElements(Class<T> type) { + if (type.getSimpleName().equals(SpringSCAPropertyElement.class.getSimpleName())) { + T[] elements = (T[])Array.newInstance(type, getPropertyElements().size()); + for (int i = 0; i < elements.length; i++) { + elements[i] = SpringElementTie.copy(getPropertyElements().get(i), type, type); + } + return elements; + } else if (type.getSimpleName().equals(SpringSCAReferenceElement.class.getSimpleName())) { + T[] elements = (T[])Array.newInstance(type, getReferenceElements().size()); + for (int i = 0; i < elements.length; i++) { + elements[i] = SpringElementTie.copy(getReferenceElements().get(i), type, type); + } + return elements; + } else if (type.getSimpleName().equals(SpringSCAServiceElement.class.getSimpleName())) { + T[] elements = (T[])Array.newInstance(type, getServiceElements().size()); + for (int i = 0; i < elements.length; i++) { + elements[i] = SpringElementTie.copy(getServiceElements().get(i), type, type); + } + return elements; + } else if (type.getSimpleName().equals(SpringBeanElement.class.getSimpleName())) { + T[] elements = (T[])Array.newInstance(type, getBeanElements().size()); + for (int i = 0; i < elements.length; i++) { + elements[i] = SpringElementTie.copy(getBeanElements().get(i), type, type); + } + return elements; + } else { + throw new IllegalArgumentException(type + " is not supported"); + } + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/context/tie/SCAParentApplicationContext.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/context/tie/SCAParentApplicationContext.java new file mode 100644 index 0000000000..d2b35ce74e --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/context/tie/SCAParentApplicationContext.java @@ -0,0 +1,212 @@ +/* + * 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.tuscany.sca.implementation.spring.context.tie; + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.util.Locale; +import java.util.Map; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.config.AutowireCapableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.MessageSourceResolvable; +import org.springframework.context.NoSuchMessageException; +import org.springframework.core.io.Resource; + +/** + * A Spring ParentApplicationContext for a given Spring Implementation + * + * The Parent application context is responsible for handling those entities within a Spring + * application context that actually belong to SCA rather than to Spring. The principal things + * are Properties and References. These may be present either through explicit <sca:property/> + * and <sca:reference/> elements in the application context or they may be implicit through + * unresolved Spring bean <property.../> elements. In either case, it is the Parent application + * context that must provide Spring beans that correspond to the property or reference, as derived + * from the SCA composite in which the Spring application context is an implementation. + * + * @version $Rev$ $Date$ + */ +public class SCAParentApplicationContext implements ApplicationContext { + + // The Spring implementation for which this is the parent application context + private SpringImplementationStub implementation; + + private static final String[] EMPTY_ARRAY = new String[0]; + + public SCAParentApplicationContext(SpringImplementationStub implementation) { + this.implementation = implementation; + } // end constructor + + public Object getBean(String name) throws BeansException { + return getBean(name, (Class)null); + } + + /** + * Get a Bean for a reference or for a property. + * + * @param name - the name of the Bean required + * @param requiredType - the required type of the Bean (either a Java class or a Java interface) + * @return Object - a Bean which matches the requested bean + */ + public Object getBean(String name, Class requiredType) throws BeansException { + Object bean = implementation.getBean(name, requiredType); + if (bean == null && getParent() != null) { + bean = getParent().getBean(name, requiredType); + } + if (bean == null) { + throw new NoSuchBeanDefinitionException("Unable to find Bean with name " + name); + } else { + return bean; + } + } // end method getBean( String, Class ) + + public Object getBean(String name, Object[] args) throws BeansException { + return getBean(name, ((Class)null)); + } + + public <T> T getBean(Class<T> clazz) throws BeansException { + return clazz.cast(getBean(clazz.getName(), clazz)); + } + + public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> clazz) throws BeansException { + return null; + } + + public <A extends Annotation> A findAnnotationOnBean(String arg0, Class<A> clazz) { + return null; + } + + public boolean containsBean(String name) { + // TODO + return false; + } + + public boolean isSingleton(String name) throws NoSuchBeanDefinitionException { + // TODO + return false; + } + + public boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException { + throw new UnsupportedOperationException(); + } + + public Class getType(String name) throws NoSuchBeanDefinitionException { + return null; + } + + public String[] getAliases(String name) throws NoSuchBeanDefinitionException { + return EMPTY_ARRAY; + } + + public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException { + return null; + } + + public String getId() { + return this.toString(); + } + + public String getDisplayName() { + return implementation.getURI(); + } + + public long getStartupDate() { + return 0; + } + + public boolean containsBeanDefinition(String beanName) { + return false; + } + + public int getBeanDefinitionCount() { + return 0; + } + + public String[] getBeanDefinitionNames() { + return new String[0]; + } + + public String[] getBeanNamesForType(Class type) { + return new String[0]; + } + + public String[] getBeanNamesForType(Class type, boolean includePrototypes, boolean includeFactoryBeans) { + return new String[0]; + } + + public Map getBeansOfType(Class type) throws BeansException { + return null; + } + + public Map getBeansOfType(Class type, boolean includePrototypes, boolean includeFactoryBeans) throws BeansException { + return null; + } + + public boolean isPrototype(String theString) { + return false; + } + + public BeanFactory getParentBeanFactory() { + return null; + } + + public boolean containsLocalBean(String name) { + return false; + } + + public String getMessage(String code, Object[] args, String defaultMessage, Locale locale) { + return null; + } + + public String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException { + return null; + } + + public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException { + return null; + } + + public void publishEvent(ApplicationEvent event) { + + } + + public Resource[] getResources(String locationPattern) throws IOException { + return new Resource[0]; + } + + public Resource getResource(String location) { + return null; + } + + public ClassLoader getClassLoader() { + // REVIEW: this is almost certainly flawed, but it's not clear how the SCA runtime's + // resource loading mechanism is exposed right now. + return this.getClass().getClassLoader(); + } + + @Override + public ApplicationContext getParent() { + return implementation.getParentApplicationContext(); + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/context/tie/SpringContextTie.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/context/tie/SpringContextTie.java new file mode 100644 index 0000000000..8bcdc8108d --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/context/tie/SpringContextTie.java @@ -0,0 +1,130 @@ +/* + * 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.tuscany.sca.implementation.spring.context.tie; + +import java.net.URL; +import java.util.List; + +import org.apache.tuscany.sca.implementation.spring.processor.tie.ComponentNameAnnotationProcessor; +import org.apache.tuscany.sca.implementation.spring.processor.tie.ComponentStub; +import org.apache.tuscany.sca.implementation.spring.processor.tie.ConstructorAnnotationProcessor; +import org.apache.tuscany.sca.implementation.spring.processor.tie.InitDestroyAnnotationProcessor; +import org.apache.tuscany.sca.implementation.spring.processor.tie.PropertyAnnotationProcessor; +import org.apache.tuscany.sca.implementation.spring.processor.tie.PropertyValueStub; +import org.apache.tuscany.sca.implementation.spring.processor.tie.ReferenceAnnotationProcessor; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.core.io.UrlResource; + +/** + * This is the runtime side tie for the corresponding tuscany side stub class. + * It enables the Tuscany code to invoke methods on a Spring context without + * needing to know about any Spring classes. See the SpringContextStub class + * in the implementation-spring module for what the stub does. + */ +public class SpringContextTie { + + private AbstractApplicationContext springContext; + private SpringImplementationStub implementation; + + public SpringContextTie(SpringImplementationStub implementation, List<URL> resource) { + this.implementation = implementation; + SCAParentApplicationContext scaParentContext = new SCAParentApplicationContext(implementation); + springContext = createApplicationContext(scaParentContext, resource); + } + + public ApplicationContext getApplicationContext() { + return springContext; + } + + public void start() { + // Do refresh here to ensure that Spring Beans are not touched before the SCA config process is complete... + springContext.refresh(); + springContext.start(); + } + + public void close() { + springContext.close(); + if (springContext instanceof GenericApplicationContext) { + springContext.stop(); + } + } + + /** + * Include BeanPostProcessor to deal with SCA Annotations in Spring Bean + */ + private AbstractApplicationContext createApplicationContext(SCAParentApplicationContext scaParentContext, + List<URL> resources) { + + GenericApplicationContext appCtx = + new SCAGenericApplicationContext(scaParentContext, implementation.getClassLoader()); + XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(appCtx); + + // REVIEW: [rfeng] How do we control the schema validation + xmlReader.setValidating(false); + + for (URL resource : resources) { + xmlReader.loadBeanDefinitions(new UrlResource(resource)); + } + xmlReader.setBeanClassLoader(implementation.getClassLoader()); + includeAnnotationProcessors(appCtx.getBeanFactory()); + return appCtx; + + } + + public Object getBean(String id) throws BeansException { + return springContext.getBean(id); + } + + /** + * Include BeanPostProcessor to deal with SCA Annotations in Spring Bean + */ + private void includeAnnotationProcessors(ConfigurableListableBeanFactory beanFactory) { + + // Processor to deal with @Init and @Destroy SCA Annotations + BeanPostProcessor initDestroyProcessor = new InitDestroyAnnotationProcessor(); + beanFactory.addBeanPostProcessor(initDestroyProcessor); + + // Processor to deal with @Reference SCA Annotations + ComponentStub component = new ComponentStub(implementation.getComponentTie()); + BeanPostProcessor referenceProcessor = new ReferenceAnnotationProcessor(component); + beanFactory.addBeanPostProcessor(referenceProcessor); + + // Processor to deal with @Property SCA Annotations + PropertyValueStub pvs = new PropertyValueStub(implementation.getPropertyValueTie()); + BeanPostProcessor propertyProcessor = new PropertyAnnotationProcessor(pvs); + beanFactory.addBeanPostProcessor(propertyProcessor); + + // Processor to deal with @ComponentName SCA Annotations + BeanPostProcessor componentNameProcessor = + new ComponentNameAnnotationProcessor(implementation.getComponentName()); + beanFactory.addBeanPostProcessor(componentNameProcessor); + + // Processor to deal with @Constructor SCA Annotations + BeanPostProcessor constructorProcessor = new ConstructorAnnotationProcessor(); + beanFactory.addBeanPostProcessor(constructorProcessor); + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/context/tie/SpringImplementationStub.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/context/tie/SpringImplementationStub.java new file mode 100644 index 0000000000..5ce52e668c --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/context/tie/SpringImplementationStub.java @@ -0,0 +1,146 @@ +/* + * 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.tuscany.sca.implementation.spring.context.tie; + +import java.lang.reflect.Method; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; + +/** + * This is the runtime side stub for the corresponding Tuscany-side stub class. + * It enables the Spring code in the runtime module to invoke methods on a + * Tuscany SpringImplementation without the Spring runtime module + * needing to know about any Tuscany classes. See the SpringImplementationTie class + * in the implementation-spring module for what the tie does. + */ +public class SpringImplementationStub { + + Object tie; + Method getURI; + Method getBean; + Method getComponentName; + Method getComponentTie; + Method getPropertyValueTie; + Method getClassLoader; + Method getParentApplicationContext; + + public SpringImplementationStub(Object tie) { + this.tie = tie; + Class<?> tieClass = tie.getClass(); + try { + getURI = tieClass.getMethod("getURI", new Class<?>[] {}); + getBean = tieClass.getMethod("getBean", new Class<?>[] {String.class, Class.class}); + getComponentName = tieClass.getMethod("getComponentName"); + getComponentTie = tieClass.getMethod("getComponentTie"); + getPropertyValueTie = tieClass.getMethod("getPropertyValueTie"); + getClassLoader = tieClass.getMethod("getClassLoader"); + getParentApplicationContext = tieClass.getMethod("getParentApplicationContext"); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public String getURI() { + try { + + return (String)getURI.invoke(tie); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Get a Bean for a reference or for a property. + * + * @param name - the name of the Bean required + * @param requiredType - the required type of the Bean (either a Java class or a Java interface) + * @return Object - a Bean which matches the requested bean + */ + public Object getBean(String name, Class<?> requiredType) throws BeansException { + try { + + Object bean = getBean.invoke(tie, new Object[] {name, requiredType}); +// if (bean == null) { +// throw new NoSuchBeanDefinitionException("Unable to find Bean with name " + name); +// } + return bean; + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public String getComponentName() { + try { + + return (String)getComponentName.invoke(tie); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public Object getComponentTie() { + try { + + return getComponentTie.invoke(tie); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public Object getPropertyValueTie() { + try { + + return getPropertyValueTie.invoke(tie); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public ClassLoader getClassLoader() { + try { + + return (ClassLoader)getClassLoader.invoke(tie); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Get the parent Spring application context set by the Tuscany runtime + * @return + */ + public ApplicationContext getParentApplicationContext() { + try { + + return (ApplicationContext)getParentApplicationContext.invoke(tie); + + } catch (Exception e) { + throw new RuntimeException(e); + } + + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/elements/tie/SpringBeanElement.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/elements/tie/SpringBeanElement.java new file mode 100644 index 0000000000..020e001a59 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/elements/tie/SpringBeanElement.java @@ -0,0 +1,129 @@ +/* + * 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.tuscany.sca.implementation.spring.elements.tie; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a <bean> element in a Spring application-context + * - this has id and className attributes + * - plus zero or more property elements as children + * + * @version $Rev$ $Date$ + */ +public class SpringBeanElement { + + private String id; + private String className = null; + private boolean innerBean = false; + private boolean abstractBean = false; + private boolean parentAttribute = false; + private boolean factoryBeanAttribute = false; + private boolean factoryMethodAttribute = false; + + private List<SpringPropertyElement> properties = new ArrayList<SpringPropertyElement>(); + private List<SpringConstructorArgElement> constructorargs = new ArrayList<SpringConstructorArgElement>(); + + public SpringBeanElement(String id, String className) { + this.id = id; + this.className = className; + } + + public String getClassName() { + return className; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public List<SpringPropertyElement> getProperties() { + return properties; + } + + public void addProperty(SpringPropertyElement property) { + properties.add(property); + } + + public List<SpringConstructorArgElement> getCustructorArgs() { + return constructorargs; + } + + public void addCustructorArgs(SpringConstructorArgElement args) { + constructorargs.add(args); + } + + public boolean isInnerBean() { + return innerBean; + } + + public void setInnerBean(boolean innerBean) { + this.innerBean = innerBean; + } + + public boolean isAbstractBean() { + return abstractBean; + } + + public void setAbstractBean(boolean abstractBean) { + this.abstractBean = abstractBean; + } + + public boolean hasParentAttribute() { + return parentAttribute; + } + + public void setParentAttribute(boolean parentAttribute) { + this.parentAttribute = parentAttribute; + } + + public boolean hasFactoryBeanAttribute() { + return factoryBeanAttribute; + } + + public void setFactoryBeanAttribute(boolean factoryBeanAttribute) { + this.factoryBeanAttribute = factoryBeanAttribute; + } + + public boolean hasFactoryMethodAttribute() { + return factoryMethodAttribute; + } + + public void setFactoryMethodAttribute(boolean factoryMethodAttribute) { + this.factoryMethodAttribute = factoryMethodAttribute; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("SpringBeanElement [id=").append(id).append(", className=").append(className) + .append(", innerBean=").append(innerBean).append(", abstractBean=").append(abstractBean) + .append(", parentAttribute=").append(parentAttribute).append(", factoryBeanAttribute=") + .append(factoryBeanAttribute).append(", factoryMethodAttribute=").append(factoryMethodAttribute) + .append(", properties=").append(properties).append(", constructorargs=").append(constructorargs) + .append("]"); + return builder.toString(); + } + +} // end class SpringBeanElement diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/elements/tie/SpringConstructorArgElement.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/elements/tie/SpringConstructorArgElement.java new file mode 100644 index 0000000000..53a972b7d8 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/elements/tie/SpringConstructorArgElement.java @@ -0,0 +1,77 @@ +/* + * 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.tuscany.sca.implementation.spring.elements.tie; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a <constructor-arg> element in a Spring application-context + * - this has ref attribute + * + * @version $Rev$ $Date$ + */ +public class SpringConstructorArgElement { + + private String type; + private int autoIndex = -1; + private int index = -1; + private List<String> refs = new ArrayList<String>(); + private List<String> values = new ArrayList<String>(); + + public SpringConstructorArgElement(String type) { + this.type = type; + } + + public String getType() { + return this.type; + } + + public List<String> getRefs() { + return this.refs; + } + + public void addRef(String ref) { + this.refs.add(ref); + } + + public int getIndex() { + return this.index; + } + + public void setIndex(int index) { + this.index = index; + } + + public int getAutoIndex() { + return this.autoIndex; + } + + public void setAutoIndex(int index) { + this.autoIndex = index; + } + + public List<String> getValues() { + return this.values; + } + + public void addValue(String value) { + this.values.add(value); + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/elements/tie/SpringElementTie.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/elements/tie/SpringElementTie.java new file mode 100644 index 0000000000..c088e5d0f2 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/elements/tie/SpringElementTie.java @@ -0,0 +1,70 @@ +/* + * 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.tuscany.sca.implementation.spring.elements.tie; + +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * A hacking utility to copy beans field by field between two class loaders + */ +public class SpringElementTie { + public static <T> T copy(Object source, Class<T> cls, Type genericType) { + if (source == null) { + return null; + } + if (cls.isPrimitive()) { + return (T)source; + } + if (Collection.class.isAssignableFrom(cls)) { + ParameterizedType pType = (ParameterizedType)genericType; + Type itemType = pType.getActualTypeArguments()[0]; + Collection col = (Collection)source; + List target = new ArrayList(); + for (Object item : col) { + target.add(copy(item, (Class<?>)itemType, itemType)); + } + return (T)target; + } + if (cls.isInstance(source)) { + return cls.cast(source); + } + try { + Class<?> sourceClass = source.getClass(); + T target = cls.newInstance(); + for (Field sourceField : sourceClass.getDeclaredFields()) { + sourceField.setAccessible(true); + Field targetField = cls.getDeclaredField(sourceField.getName()); + targetField.setAccessible(true); + Object sourceFieldValue = sourceField.get(source); + Object targetFieldValue = copy(sourceFieldValue, targetField.getType(), targetField.getGenericType()); + targetField.set(target, targetFieldValue); + } + return target; + } catch (Throwable e) { + throw new IllegalArgumentException(e); + } + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/elements/tie/SpringPropertyElement.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/elements/tie/SpringPropertyElement.java new file mode 100644 index 0000000000..c0a1f2129b --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/elements/tie/SpringPropertyElement.java @@ -0,0 +1,68 @@ +/* + * 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.tuscany.sca.implementation.spring.elements.tie; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a <property> element in a Spring application-context + * - this has name and ref attributes + * + * @version $Rev$ $Date$ + */ +public class SpringPropertyElement { + + private String name; + private List<String> refs = new ArrayList<String>(); + private List<String> values = new ArrayList<String>(); + + public SpringPropertyElement(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public List<String> getRefs() { + return this.refs; + } + + public void addRef(String ref) { + this.refs.add(ref); + } + + public List<String> getValues() { + return this.values; + } + + public void addValue(String value) { + this.values.add(value); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("SpringPropertyElement [name=").append(name).append(", refs=").append(refs).append(", values=") + .append(values).append("]"); + return builder.toString(); + } + +} // end class SpringPropertyElement diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/elements/tie/SpringSCAPropertyElement.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/elements/tie/SpringSCAPropertyElement.java new file mode 100644 index 0000000000..3f9901abea --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/elements/tie/SpringSCAPropertyElement.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.tuscany.sca.implementation.spring.elements.tie; + +/** + * Represents an <sca:property> element in a Spring application-context + * - this has name and type attributes + * @version $Rev$ $Date$ + */ +public class SpringSCAPropertyElement { + + private String name; + private String type; + + public SpringSCAPropertyElement(String name, String type) { + this.name = name; + this.type = type; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setType(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("SpringSCAPropertyElement [name=").append(name).append(", type=").append(type).append("]"); + return builder.toString(); + } + +} // end class SpringPropertyElement diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/elements/tie/SpringSCAReferenceElement.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/elements/tie/SpringSCAReferenceElement.java new file mode 100644 index 0000000000..7569d2996f --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/elements/tie/SpringSCAReferenceElement.java @@ -0,0 +1,73 @@ +/* + * 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.tuscany.sca.implementation.spring.elements.tie; + + +/** + * Represents a <sca:reference> element in a Spring application-context + * - this has id and className attributes + * - plus zero or more property elements as children + * + * @version $Rev$ $Date$ + */ +public class SpringSCAReferenceElement { + + private String name; + private String type; + private String defaultBean; + + public SpringSCAReferenceElement(String name, String type) { + this.name = name; + this.type = type; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setType(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + public void setDefaultBean(String defaultBean) { + this.defaultBean = defaultBean; + } + + public String getDefaultBean() { + return defaultBean; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("SpringSCAReferenceElement [name=").append(name).append(", type=").append(type) + .append(", defaultBean=").append(defaultBean).append("]"); + return builder.toString(); + } + + +} // end class SpringSCAReferenceElement diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/elements/tie/SpringSCAServiceElement.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/elements/tie/SpringSCAServiceElement.java new file mode 100644 index 0000000000..737abe7c04 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/elements/tie/SpringSCAServiceElement.java @@ -0,0 +1,73 @@ +/* + * 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.tuscany.sca.implementation.spring.elements.tie; + + +/** + * Represents a <sca:service> element in a Spring application-context + * - this has id and className attributes + * - plus zero or more property elements as children + * + * @version $Rev$ $Date$ + */ +public class SpringSCAServiceElement { + + private String name; + private String type; + private String target; + + + public SpringSCAServiceElement(String name, String target) { + this.name = name; + this.target = target; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setType(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + public void setTarget(String target) { + this.target = target; + } + + public String getTarget() { + return target; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("SpringSCAServiceElement [name=").append(name).append(", type=").append(type) + .append(", target=").append(target).append("]"); + return builder.toString(); + } + +} // end class SpringSCAServiceElement diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/tie/SCANamespaceHandlerResolver.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/tie/SCANamespaceHandlerResolver.java new file mode 100644 index 0000000000..07c7c6a454 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/tie/SCANamespaceHandlerResolver.java @@ -0,0 +1,53 @@ +/* + * 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.tuscany.sca.implementation.spring.namespace.tie; + +import org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver; +import org.springframework.beans.factory.xml.NamespaceHandler; + +/** + * Overrides the default Spring namespace resolver to automatically register + * {@link ScaNamespaceHandler} instead of requiring a value to be supplied in a + * Spring configuration + * + * @version $Rev$ $Date$ + */ +public class SCANamespaceHandlerResolver extends DefaultNamespaceHandlerResolver { + private static final String SCA_NAMESPACE = "http://www.springframework.org/schema/sca"; + + private ScaNamespaceHandler handler; + + public SCANamespaceHandlerResolver(ClassLoader classLoader) { + super(classLoader); + handler = new ScaNamespaceHandler(/*componentType*/); + } + + public SCANamespaceHandlerResolver(String handlerMappingsLocation, ClassLoader classLoader) { + super(classLoader, handlerMappingsLocation); + handler = new ScaNamespaceHandler(/*componentType*/); + } + + @Override + public NamespaceHandler resolve(String namespaceUri) { + if (SCA_NAMESPACE.equals(namespaceUri)) { + return handler; + } + return super.resolve(namespaceUri); + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/tie/ScaNamespaceHandler.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/tie/ScaNamespaceHandler.java new file mode 100644 index 0000000000..6ed49abb6f --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/tie/ScaNamespaceHandler.java @@ -0,0 +1,38 @@ +/* + * Copyright 2002-2006 the original author or authors. + * + * Licensed 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.tuscany.sca.implementation.spring.namespace.tie; + +import org.springframework.beans.factory.xml.NamespaceHandlerSupport; + +/** + * Handler for the <sca:> namespace in an application context + * + * @version $Rev$ $Date$ + */ +public class ScaNamespaceHandler extends NamespaceHandlerSupport { + + public ScaNamespaceHandler() { + } + + @Override + public void init() { + registerBeanDefinitionParser("reference", new ScaReferenceBeanDefinitionParser()); + registerBeanDefinitionParser("service", new ScaServiceBeanDefinitionParser()); + registerBeanDefinitionParser("property", new ScaPropertyBeanDefinitionParser()); + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/tie/ScaPropertyBeanDefinitionParser.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/tie/ScaPropertyBeanDefinitionParser.java new file mode 100644 index 0000000000..ad11a300ae --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/tie/ScaPropertyBeanDefinitionParser.java @@ -0,0 +1,44 @@ +/* + * Copyright 2002-2006 the original author or authors. + * + * Licensed 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.tuscany.sca.implementation.spring.namespace.tie; + +import org.apache.tuscany.sca.implementation.spring.context.tie.SCAGenericApplicationContext; +import org.apache.tuscany.sca.implementation.spring.elements.tie.SpringSCAPropertyElement; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.xml.BeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.w3c.dom.Element; + +/** + * Parser for the <sca:reference> element + * @version $Rev$ $Date$ + */ +public class ScaPropertyBeanDefinitionParser implements BeanDefinitionParser { + + public BeanDefinition parse(Element element, ParserContext parserContext) { + BeanDefinitionRegistry registry = parserContext.getRegistry(); + if (registry instanceof SCAGenericApplicationContext) { + SCAGenericApplicationContext context = (SCAGenericApplicationContext)registry; + SpringSCAPropertyElement propertyElement = + new SpringSCAPropertyElement(element.getAttributeNS(null, "name"), element.getAttributeNS(null, "type")); + context.addSCAPropertyElement(propertyElement); + } + // do nothing, this is handled by Tuscany + return null; + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/tie/ScaReferenceBeanDefinitionParser.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/tie/ScaReferenceBeanDefinitionParser.java new file mode 100644 index 0000000000..a4fefa70f1 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/tie/ScaReferenceBeanDefinitionParser.java @@ -0,0 +1,49 @@ +/* + * Copyright 2002-2006 the original author or authors. + * + * Licensed 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.tuscany.sca.implementation.spring.namespace.tie; + +import org.apache.tuscany.sca.implementation.spring.context.tie.SCAGenericApplicationContext; +import org.apache.tuscany.sca.implementation.spring.elements.tie.SpringSCAReferenceElement; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.xml.BeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.w3c.dom.Element; + +/** + * Parser for the <sca:reference> element + * + * @version $Rev$ $Date$ + */ +public class ScaReferenceBeanDefinitionParser implements BeanDefinitionParser { + + public BeanDefinition parse(Element element, ParserContext parserContext) { + BeanDefinitionRegistry registry = parserContext.getRegistry(); + if (registry instanceof SCAGenericApplicationContext) { + SCAGenericApplicationContext context = (SCAGenericApplicationContext)registry; + SpringSCAReferenceElement referenceElement = + new SpringSCAReferenceElement(element.getAttributeNS(null, "name"), + element.getAttributeNS(null, "type")); + referenceElement.setDefaultBean(element.getAttributeNS(null, "default")); + context.addSCAReferenceElement(referenceElement); + } + + // do nothing, this is handled by Tuscany + return null; + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/tie/ScaServiceBeanDefinitionParser.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/tie/ScaServiceBeanDefinitionParser.java new file mode 100644 index 0000000000..64f4ce20dc --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/tie/ScaServiceBeanDefinitionParser.java @@ -0,0 +1,48 @@ +/* + * Copyright 2002-2006 the original author or authors. + * + * Licensed 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.tuscany.sca.implementation.spring.namespace.tie; + +import org.apache.tuscany.sca.implementation.spring.context.tie.SCAGenericApplicationContext; +import org.apache.tuscany.sca.implementation.spring.elements.tie.SpringSCAServiceElement; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.xml.BeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.w3c.dom.Element; + +/** + * Parser for the <sca:service/> element + * + * @version $Rev$ $Date$ + */ +public class ScaServiceBeanDefinitionParser implements BeanDefinitionParser { + + public BeanDefinition parse(Element element, ParserContext parserContext) { + BeanDefinitionRegistry registry = parserContext.getRegistry(); + if (registry instanceof SCAGenericApplicationContext) { + SCAGenericApplicationContext context = (SCAGenericApplicationContext)registry; + SpringSCAServiceElement serviceElement = + new SpringSCAServiceElement(element.getAttributeNS(null, "name"), + element.getAttributeNS(null, "target")); + serviceElement.setType(element.getAttributeNS(null, "type")); + context.addSCAServiceElement(serviceElement); + } + // do nothing, handled by Tuscany + return null; + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/tie/ComponentNameAnnotationProcessor.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/tie/ComponentNameAnnotationProcessor.java new file mode 100644 index 0000000000..77f9f30bfd --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/tie/ComponentNameAnnotationProcessor.java @@ -0,0 +1,151 @@ +/* + * 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.tuscany.sca.implementation.spring.processor.tie; + +import java.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; +import java.lang.ref.Reference; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import org.oasisopen.sca.annotation.ComponentName; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.FatalBeanException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.util.Assert; +import org.springframework.util.ReflectionUtils; + +public class ComponentNameAnnotationProcessor implements BeanPostProcessor { + + private Class<? extends Annotation> componentNameAnnotationType = ComponentName.class; + + private String componentName; + + public ComponentNameAnnotationProcessor(String componentName) { + this.componentName = componentName; + } + + /** + * Gets componentName annotation type. + */ + protected Class<? extends Annotation> getComponentNameAnnotationType() { + return this.componentNameAnnotationType; + } + + /** + * Sets componentName annotation type. + */ + public void setComponentNameAnnotationType(Class<? extends Annotation> componentNameAnnotationType) { + Assert.notNull(componentNameAnnotationType, "'componentNameAnnotationType' type must not be null."); + this.componentNameAnnotationType = componentNameAnnotationType; + } + + /** + * This method is used to execute before a bean's initialization callback. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String) + */ + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + processAnnotation(bean); + return bean; + } + + /** + * This method is used to execute after a bean's initialization callback. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String) + */ + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + /** + * <p>Processes a beans fields for injection if it has a {@link Reference} annotation.</p> + */ + protected void processAnnotation(final Object bean) { + + final Class<?> clazz = bean.getClass(); + + ReflectionUtils.doWithFields(clazz, new ReflectionUtils.FieldCallback() { + public void doWith(Field field) { + Annotation annotation = field.getAnnotation(getComponentNameAnnotationType()); + + if (annotation != null) { + if (Modifier.isStatic(field.getModifiers())) { + throw new IllegalStateException("ComponentName annotation is not supported on static fields"); + } + + if (Modifier.isPrivate(field.getModifiers())) { + throw new IllegalStateException("ComponentName annotation is not supported on private fields"); + } + + ReflectionUtils.makeAccessible(field); + + if (field.getType().getName().equals("java.lang.String")) { + Object nameObj = componentName; + if (nameObj != null) + ReflectionUtils.setField(field, bean, nameObj); + } else { + throw new IllegalStateException( + "ComponentName annotation is supported only on java.lang.String field type."); + } + } + } + }); + + ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() { + public void doWith(Method method) { + Annotation annotation = method.getAnnotation(getComponentNameAnnotationType()); + + if (annotation != null) { + if (Modifier.isStatic(method.getModifiers())) { + throw new IllegalStateException("ComponentName annotation is not supported on static methods"); + } + + if (Modifier.isPrivate(method.getModifiers())) { + throw new IllegalStateException("ComponentName annotation is not supported on private methods"); + } + + if (method.getParameterTypes().length == 0) { + throw new IllegalStateException( + "ComponentName annotation requires at least one argument: " + method); + } + + PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method); + + if (pd.getPropertyType().getName().equals("java.lang.String")) { + Object nameObj = componentName; + if (nameObj != null) { + try { + pd.getWriteMethod().invoke(bean, new Object[] {nameObj}); + } catch (Throwable e) { + throw new FatalBeanException("Problem injecting reference: " + e.getMessage(), e); + } + } + } else { + throw new IllegalStateException( + "ComponentName annotation is supported only on java.lang.String field type."); + } + } + } + }); + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/tie/ComponentStub.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/tie/ComponentStub.java new file mode 100644 index 0000000000..7511ac4bd5 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/tie/ComponentStub.java @@ -0,0 +1,54 @@ +/* + * 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.tuscany.sca.implementation.spring.processor.tie; + +import java.lang.reflect.Method; + +/** + * This is the Spring runtime side stub for the corresponding Tuscany tie class. + * It enables the Tuscany code to invoke methods on a Spring context without + * needing to know about any Spring classes. See the ComponentTie class + * in the implementation-spring module for what the tie does. + */ +public class ComponentStub { + + private Object tie; + private Method getService; + + public ComponentStub(Object tie) { + this.tie = tie; + Class<?> tieClass = tie.getClass(); + try { + getService = tieClass.getMethod("getService", new Class<?>[] {Class.class, String.class}); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public Object getService(Class<?> type, String name) { + try { + + return getService.invoke(tie, type, name); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/tie/ConstructorAnnotationProcessor.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/tie/ConstructorAnnotationProcessor.java new file mode 100644 index 0000000000..503307cfd9 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/tie/ConstructorAnnotationProcessor.java @@ -0,0 +1,112 @@ +/* + * 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.tuscany.sca.implementation.spring.processor.tie; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter; +import org.springframework.util.Assert; + +public class ConstructorAnnotationProcessor extends InstantiationAwareBeanPostProcessorAdapter { + + private Class<? extends Annotation> constructorAnnotationType = org.oasisopen.sca.annotation.Constructor.class; + + private Class<? extends Annotation> autowiredAnnotationType = Autowired.class; + + public ConstructorAnnotationProcessor() { + // Default constructor. + } + + /** + * Set the 'autowired' annotation type, to be used on constructors, fields, + * setter methods and arbitrary config methods. + */ + public void setAutowiredAnnotationType(Class<? extends Annotation> autowiredAnnotationType) { + Assert.notNull(autowiredAnnotationType, "'autowiredAnnotationType' must not be null"); + this.autowiredAnnotationType = autowiredAnnotationType; + } + + /** + * Return the 'autowired' annotation type. + */ + protected Class<? extends Annotation> getAutowiredAnnotationType() { + return this.autowiredAnnotationType; + } + + /** + * Return the 'constructor' annotation type. + */ + protected Class<? extends Annotation> getConstructorAnnotationType() { + return this.constructorAnnotationType; + } + + /** + * Sets the 'constructor' annotation type. + */ + public void setConstructorAnnotationType(Class<? extends Annotation> constructorAnnotationType) { + Assert.notNull(constructorAnnotationType, "'constructorAnnotationType' type must not be null."); + this.constructorAnnotationType = constructorAnnotationType; + } + + /** + * This method is used to execute before a bean's initialization callback. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String) + */ + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + /** + * This method is used to execute after a bean's initialization callback. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String) + */ + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + public Constructor[] determineCandidateConstructors(Class beanClass, String beanName) throws BeansException { + /*Constructor[] declaredConstructors = beanClass.getDeclaredConstructors(); + Method[] declaredMethods = beanClass.getDeclaredMethods(); + List candidates = new ArrayList(declaredConstructors.length); + + for (int i = 0; i < declaredMethods.length; i++) { + Method method = declaredMethods[i]; + Annotation annotation = method.getAnnotation(getConstructorAnnotationType()); + if (annotation != null) { + if (Modifier.isStatic(method.getModifiers())) { + throw new IllegalStateException("Constructor annotation is not supported on static methods"); + } + + if (candidates.size() == 1) { + throw new IllegalStateException("Only one method is allowed to have constructor annotation in a bean: " + method); + } + + candidates.add(method); + } + } + + return (Constructor[]) candidates.toArray(new Constructor[candidates.size()]);*/ + return null; + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/tie/InitDestroyAnnotationProcessor.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/tie/InitDestroyAnnotationProcessor.java new file mode 100644 index 0000000000..390ee040f2 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/tie/InitDestroyAnnotationProcessor.java @@ -0,0 +1,75 @@ +/* + * 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.tuscany.sca.implementation.spring.processor.tie; + +import java.lang.annotation.Annotation; + +import org.oasisopen.sca.annotation.Destroy; +import org.oasisopen.sca.annotation.Init; +import org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor; + +public class InitDestroyAnnotationProcessor extends InitDestroyAnnotationBeanPostProcessor { + + private static final long serialVersionUID = 0; + + private Class<? extends Annotation> initAnnotationType = Init.class; + private Class<? extends Annotation> destroyAnnotationType = Destroy.class; + + /** + * Gets init annotation type. + */ + protected Class<? extends Annotation> getInitAnnotationType() { + return this.initAnnotationType; + } + + /** + * Sets init annotation type. + */ + /* + * public void setInitAnnotationType(Class<? extends Annotation> + * initAnnotationType) { Assert.notNull(initAnnotationType, + * "Init annotation type must not be null."); this.initAnnotationType = + * initAnnotationType; } + */ + + /** + * Gets destroy annotation type. + */ + protected Class<? extends Annotation> getDestroyAnnotationType() { + return this.destroyAnnotationType; + } + + /** + * Sets destroy annotation type. + */ + /* + * public void setDestroyAnnotationType(Class<? extends Annotation> + * destroyAnnotationType) { Assert.notNull(destroyAnnotationType, + * "Destroy annotation type must not be null."); this.destroyAnnotationType + * = destroyAnnotationType; } + */ + + public InitDestroyAnnotationProcessor() { + // Set the @Init annotation type + setInitAnnotationType(initAnnotationType); + + // Set the @Destroy annotation type + setDestroyAnnotationType(destroyAnnotationType); + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/tie/PropertyAnnotationProcessor.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/tie/PropertyAnnotationProcessor.java new file mode 100644 index 0000000000..ce3aafd3ef --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/tie/PropertyAnnotationProcessor.java @@ -0,0 +1,163 @@ +/* + * 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.tuscany.sca.implementation.spring.processor.tie; + +import java.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import org.oasisopen.sca.annotation.Property; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.FatalBeanException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.util.Assert; +import org.springframework.util.ReflectionUtils; + +public class PropertyAnnotationProcessor implements BeanPostProcessor { + + private Class<? extends Annotation> propertyAnnotationType = Property.class; + + private PropertyValueStub propertyValue; + + public PropertyAnnotationProcessor(PropertyValueStub propertyValue) { + this.propertyValue = propertyValue; + } + + /** + * Gets property annotation type. + */ + protected Class<? extends Annotation> getPropertyAnnotationType() { + return this.propertyAnnotationType; + } + + /** + * Sets property annotation type. + */ + public void setPropertyAnnotationType(Class<? extends Annotation> propertyAnnotationType) { + Assert.notNull(propertyAnnotationType, "'propertyAnnotationType' type must not be null."); + this.propertyAnnotationType = propertyAnnotationType; + } + + /** + * This method is used to execute before a bean's initialization callback. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String) + */ + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + processAnnotation(bean); + return bean; + } + + /** + * This method is used to execute after a bean's initialization callback. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String) + */ + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + /** + * <p>Processes a beans fields for injection if it has a {@link Property} annotation.</p> + */ + protected void processAnnotation(final Object bean) { + + final Class<?> clazz = bean.getClass(); + + ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() { + public void doWith(Method method) { + + Property annotation = (Property)method.getAnnotation(getPropertyAnnotationType()); + + if (annotation != null) { + if (Modifier.isStatic(method.getModifiers())) { + throw new IllegalStateException("Property annotation is not supported on static methods"); + } + + /* + if (Modifier.isPrivate(method.getModifiers())) { + throw new IllegalStateException("Property annotation is not supported on private methods"); + } + */ + + if (method.getParameterTypes().length == 0) { + throw new IllegalStateException("Property annotation requires at least one argument: " + method); + } + + PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method); + if (pd != null) { + String propName = annotation.name(); + if ("".equals(propName)) { + injectProperty(bean, pd, propertyValue.getPropertyObj(pd.getPropertyType(), pd.getName())); + } else { + injectProperty(bean, pd, propertyValue.getPropertyObj(pd.getPropertyType(), propName)); + } + } + } + } + }); + + ReflectionUtils.doWithFields(clazz, new ReflectionUtils.FieldCallback() { + public void doWith(Field field) { + + Property annotation = (Property)field.getAnnotation(getPropertyAnnotationType()); + + if (annotation != null) { + if (Modifier.isStatic(field.getModifiers())) { + throw new IllegalStateException("Property annotation is not supported on static fields"); + } + + /* + if (Modifier.isPrivate(field.getModifiers())) { + throw new IllegalStateException("Property annotation is not supported on private fields"); + } + */ + + ReflectionUtils.makeAccessible(field); + + Object propertyObj = null; + String propName = annotation.name(); + if ("".equals(propName)) { + propertyObj = propertyValue.getPropertyObj(field.getType(), field.getName()); + } else { + propertyObj = propertyValue.getPropertyObj(field.getType(), propName); + } + + if (propertyObj != null) + ReflectionUtils.setField(field, bean, propertyObj); + } + } + }); + } + + public void injectProperty(Object bean, PropertyDescriptor pd, Object propertyObj) { + + if (propertyObj != null) { + try { + pd.getWriteMethod().invoke(bean, new Object[] {propertyObj}); + } catch (Throwable e) { + throw new FatalBeanException("Problem injecting property: " + e.getMessage(), e); + } + } + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/tie/PropertyValueStub.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/tie/PropertyValueStub.java new file mode 100644 index 0000000000..5a4b57ce81 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/tie/PropertyValueStub.java @@ -0,0 +1,55 @@ +/* + * 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.tuscany.sca.implementation.spring.processor.tie; + +import java.lang.reflect.Method; + +/** + * This is the Spring runtime side stub for the corresponding Tuscany tie class. + * It enables the Tuscany code to invoke methods on a Spring context without + * needing to know about any Spring classes. See the PropertyValueTie class + * in the implementation-spring module for what the tie does. + */ +public class PropertyValueStub { + + private Object tie; + private Method getPropertyObj; + + public PropertyValueStub(Object tie) { + this.tie = tie; + Class<?> tieClass = tie.getClass(); + try { + getPropertyObj = tieClass.getMethod("getPropertyObj", new Class<?>[] {Class.class, String.class}); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public Object getPropertyObj(Class<?> propertyType, String name) { + try { + + return getPropertyObj.invoke(tie, propertyType, name); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/tie/ReferenceAnnotationProcessor.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/tie/ReferenceAnnotationProcessor.java new file mode 100644 index 0000000000..24761d2cfa --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/tie/ReferenceAnnotationProcessor.java @@ -0,0 +1,167 @@ +/* + * 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.tuscany.sca.implementation.spring.processor.tie; + +import java.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import org.oasisopen.sca.annotation.Reference; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.FatalBeanException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.util.Assert; +import org.springframework.util.ReflectionUtils; + +public class ReferenceAnnotationProcessor implements BeanPostProcessor { + + private Class<? extends Annotation> referenceAnnotationType = Reference.class; + private ComponentStub component; + + public ReferenceAnnotationProcessor(ComponentStub component) { + this.component = component; + } + + /** + * Gets referece annotation type. + */ + protected Class<? extends Annotation> getReferenceAnnotationType() { + return this.referenceAnnotationType; + } + + /** + * Sets referece annotation type. + */ + public void setReferenceAnnotationType(Class<? extends Annotation> referenceAnnotationType) { + Assert.notNull(referenceAnnotationType, "'referenceAnnotationType' type must not be null."); + this.referenceAnnotationType = referenceAnnotationType; + } + + /** + * This method is used to execute before a bean's initialization callback. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String) + */ + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + processAnnotation(bean); + return bean; + } + + /** + * This method is used to execute after a bean's initialization callback. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String) + */ + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + /** + * <p>Processes a beans fields for injection if it has a {@link Reference} annotation.</p> + */ + protected void processAnnotation(final Object bean) { + + final Class<?> clazz = bean.getClass(); + + ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() { + public void doWith(Method method) { + + Reference annotation = (Reference)method.getAnnotation(getReferenceAnnotationType()); + + if (annotation != null) { + if (Modifier.isStatic(method.getModifiers())) { + throw new IllegalStateException("Reference annotation is not supported on static methods"); + } + + /* + if (Modifier.isPrivate(method.getModifiers())) { + throw new IllegalStateException("Reference annotation is not supported on private methods"); + } + */ + + if (method.getParameterTypes().length == 0) { + throw new IllegalStateException( + "Reference annotation requires at least one argument: " + method); + } + + PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method); + if (pd != null) { + String refName = annotation.name(); + if ("".equals(refName)) { + injectReference(bean, pd, pd.getName()); + } else { + injectReference(bean, pd, refName); + } + } + } + } + }); + + ReflectionUtils.doWithFields(clazz, new ReflectionUtils.FieldCallback() { + public void doWith(Field field) { + + Reference annotation = (Reference)field.getAnnotation(getReferenceAnnotationType()); + + if (annotation != null) { + if (Modifier.isStatic(field.getModifiers())) { + throw new IllegalStateException("Reference annotation is not supported on static fields"); + } + + /* + if (Modifier.isPrivate(field.getModifiers())) { + throw new IllegalStateException("Reference annotation is not supported on private fields"); + } + */ + + ReflectionUtils.makeAccessible(field); + + Object referenceObj = null; + String refName = annotation.name(); + if ("".equals(refName)) { + referenceObj = component.getService(field.getType(), field.getName()); + } else { + referenceObj = component.getService(field.getType(), refName); + } + + if (referenceObj != null) + ReflectionUtils.setField(field, bean, referenceObj); + } + } + }); + } + + /** + * Processes a property descriptor to inject a service. + */ + public void injectReference(Object bean, PropertyDescriptor pd, String name) { + + Object referenceObj = component.getService(pd.getPropertyType(), name); + + if (referenceObj != null) { + try { + pd.getWriteMethod().invoke(bean, new Object[] {referenceObj}); + } catch (Throwable e) { + throw new FatalBeanException("Problem injecting reference: " + e.getMessage(), e); + } + } + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/tie/SpringXMLLoaderTie.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/tie/SpringXMLLoaderTie.java new file mode 100644 index 0000000000..82aa176219 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/tie/SpringXMLLoaderTie.java @@ -0,0 +1,57 @@ +/* + * 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.tuscany.sca.implementation.spring.processor.tie; + +import java.net.URL; +import java.util.List; + +import org.apache.tuscany.sca.implementation.spring.context.tie.SCAGenericApplicationContext; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; +import org.springframework.context.ApplicationContext; +import org.springframework.core.io.UrlResource; + +/** + * A tie that allows Tuscany to call Spring library to load the application context for the purpose of introspection + */ +public class SpringXMLLoaderTie { + + public static ApplicationContext createApplicationContext(Object scaParentContext, + ClassLoader classLoader, + List<URL> resources) { + if (classLoader == null) { + classLoader = Thread.currentThread().getContextClassLoader(); + } + + SCAGenericApplicationContext appCtx = + new SCAGenericApplicationContext((ApplicationContext)scaParentContext, classLoader); + XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(appCtx); + + // REVIEW: [rfeng] How do we control the schema validation + xmlReader.setValidating(false); + + for (URL resource : resources) { + xmlReader.loadBeanDefinitions(new UrlResource(resource)); + } + + return appCtx; + + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/resources/META-INF/spring.handlers b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/resources/META-INF/spring.handlers new file mode 100644 index 0000000000..e7b61bfe48 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/resources/META-INF/spring.handlers @@ -0,0 +1 @@ +http\://www.springframework.org/schema/sca=org.apache.tuscany.sca.implementation.spring.namespace.tie.ScaNamespaceHandler
diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/resources/META-INF/spring.schemas b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/resources/META-INF/spring.schemas new file mode 100644 index 0000000000..249cc21c13 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/resources/META-INF/spring.schemas @@ -0,0 +1 @@ +http\://www.osoa.org/xmlns/sca/1.0/spring-sca.xsd=org/springframework/sca/xml/spring-sca.xsd diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/resources/org/springframework/sca/xml/spring-sca.xsd b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/resources/org/springframework/sca/xml/spring-sca.xsd new file mode 100644 index 0000000000..dfa0b931f6 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring-tie/src/main/resources/org/springframework/sca/xml/spring-sca.xsd @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<xsd:schema xmlns="http://www.springframework.org/schema/sca" xmlns:xsd="http://www.w3.org/2001/XMLSchema" + attributeFormDefault="unqualified" elementFormDefault="qualified" + targetNamespace="http://www.springframework.org/schema/sca"> + + <xsd:element name="reference"> + <xsd:complexType> + <xsd:attribute name="name" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:string" /> + </xsd:simpleType> + </xsd:attribute> + <xsd:attribute name="type" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:string" /> + </xsd:simpleType> + </xsd:attribute> + <xsd:attribute name="default" use="optional"> + <xsd:simpleType> + <xsd:restriction base="xsd:string" /> + </xsd:simpleType> + </xsd:attribute> + </xsd:complexType> + </xsd:element> + + <xsd:element name="property"> + <xsd:complexType> + <xsd:attribute name="id" use="optional"> + <xsd:simpleType> + <xsd:restriction base="xsd:string" /> + </xsd:simpleType> + </xsd:attribute> + <xsd:attribute name="name" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:string" /> + </xsd:simpleType> + </xsd:attribute> + <xsd:attribute name="type" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:string" /> + </xsd:simpleType> + </xsd:attribute> + </xsd:complexType> + </xsd:element> + + <xsd:element name="service"> + <xsd:complexType> + <xsd:attribute name="name" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:string" /> + </xsd:simpleType> + </xsd:attribute> + <xsd:attribute name="type" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:string" /> + </xsd:simpleType> + </xsd:attribute> + <xsd:attribute name="target" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:string" /> + </xsd:simpleType> + </xsd:attribute> + </xsd:complexType> + </xsd:element> + +</xsd:schema> diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/LICENSE b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/LICENSE new file mode 100644 index 0000000000..6e529a25c4 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/LICENSE @@ -0,0 +1,205 @@ +
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed 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.
+
+
+
diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/META-INF/MANIFEST.MF b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..9226b047d7 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/META-INF/MANIFEST.MF @@ -0,0 +1,50 @@ +Manifest-Version: 1.0
+SCA-Version: 1.1
+Bundle-Name: Apache Tuscany SCA Spring Implementation Model
+Bundle-Vendor: The Apache Software Foundation
+Bundle-Version: 2.0.0
+Bundle-ManifestVersion: 2
+Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
+Bundle-Description: Apache Tuscany SCA Spring Implementation Model
+Import-Package: javax.jws,
+ javax.xml.namespace,
+ javax.xml.stream,
+ org.apache.tuscany.sca.assembly;version="2.0.0",
+ org.apache.tuscany.sca.assembly.builder;version="2.0.0",
+ org.apache.tuscany.sca.assembly.impl;version="2.0.0",
+ org.apache.tuscany.sca.assembly.xml;version="2.0.0",
+ org.apache.tuscany.sca.context;version="2.0.0",
+ org.apache.tuscany.sca.contribution;version="2.0.0",
+ org.apache.tuscany.sca.contribution.processor;version="2.0.0",
+ org.apache.tuscany.sca.contribution.resolver;version="2.0.0",
+ org.apache.tuscany.sca.core;version="2.0.0",
+ org.apache.tuscany.sca.core.factory;version="2.0.0",
+ org.apache.tuscany.sca.core.invocation;version="2.0.0",
+ org.apache.tuscany.sca.databinding;version="2.0.0",
+ org.apache.tuscany.sca.databinding.impl;version="2.0.0",
+ org.apache.tuscany.sca.implementation.java;version="2.0.0",
+ org.apache.tuscany.sca.implementation.java.injection;version="2.0.0",
+ org.apache.tuscany.sca.implementation.java.introspect;version="2.0.0",
+ org.apache.tuscany.sca.implementation.java.introspect.impl;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef.java;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef.java.impl;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef.util;version="2.0.0",
+ org.apache.tuscany.sca.invocation;version="2.0.0",
+ org.apache.tuscany.sca.monitor;version="2.0.0",
+ org.apache.tuscany.sca.policy;version="2.0.0",
+ org.apache.tuscany.sca.provider;version="2.0.0",
+ org.apache.tuscany.sca.runtime;version="2.0.0",
+ org.oasisopen.sca;version="2.0.0",
+ org.oasisopen.sca.annotation;version="2.0.0"
+Bundle-SymbolicName: org.apache.tuscany.sca.implementation.spring
+Bundle-DocURL: http://www.apache.org/
+Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6 +Export-Package: org.apache.tuscany.sca.implementation.spring;version="2.0.0",
+ org.apache.tuscany.sca.implementation.spring.xml;version="2.0.0";
+ uses:="javax.xml.stream,
+ org.apache.tuscany.sca.contribution.resolver,
+ org.apache.tuscany.sca.implementation.spring,
+ org.apache.tuscany.sca.contribution.processor,
+ org.apache.tuscany.sca.core,
+ javax.xml.namespace"
diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/NOTICE b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/NOTICE new file mode 100644 index 0000000000..1325efd8bf --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/NOTICE @@ -0,0 +1,6 @@ +${pom.name}
+Copyright (c) 2005 - 2008 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/pom.xml b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/pom.xml new file mode 100644 index 0000000000..371bde71b9 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/pom.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<project> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-modules</artifactId> + <version>2.0-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>tuscany-implementation-spring</artifactId> + <name>Apache Tuscany SCA Spring Implementation Model</name> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-assembly</artifactId> + <version>2.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-assembly-xml</artifactId> + <version>2.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-contribution</artifactId> + <version>2.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-sca-api</artifactId> + <version>2.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-implementation-java</artifactId> + <version>2.0-SNAPSHOT</version> + </dependency> + + </dependencies> +</project> diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringBeanElement.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringBeanElement.java new file mode 100644 index 0000000000..64b36a0a44 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringBeanElement.java @@ -0,0 +1,132 @@ +/* + * 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.tuscany.sca.implementation.spring; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a <bean> element in a Spring application-context + * - this has id and className attributes + * - plus zero or more property elements as children + * + * @version $Rev$ $Date$ + */ +public class SpringBeanElement { + + private String id; + private String className = null; + private boolean innerBean = false; + private boolean abstractBean = false; + private boolean parentAttribute = false; + private boolean factoryBeanAttribute = false; + private boolean factoryMethodAttribute = false; + + private List<SpringPropertyElement> properties = new ArrayList<SpringPropertyElement>(); + private List<SpringConstructorArgElement> constructorargs = new ArrayList<SpringConstructorArgElement>(); + + public SpringBeanElement() { + } + + public SpringBeanElement(String id, String className) { + this.id = id; + this.className = className; + } + + public String getClassName() { + return className; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public List<SpringPropertyElement> getProperties() { + return properties; + } + + public void addProperty(SpringPropertyElement property) { + properties.add(property); + } + + public List<SpringConstructorArgElement> getCustructorArgs() { + return constructorargs; + } + + public void addCustructorArgs(SpringConstructorArgElement args) { + constructorargs.add(args); + } + + public boolean isInnerBean() { + return innerBean; + } + + public void setInnerBean(boolean innerBean) { + this.innerBean = innerBean; + } + + public boolean isAbstractBean() { + return abstractBean; + } + + public void setAbstractBean(boolean abstractBean) { + this.abstractBean = abstractBean; + } + + public boolean hasParentAttribute() { + return parentAttribute; + } + + public void setParentAttribute(boolean parentAttribute) { + this.parentAttribute = parentAttribute; + } + + public boolean hasFactoryBeanAttribute() { + return factoryBeanAttribute; + } + + public void setFactoryBeanAttribute(boolean factoryBeanAttribute) { + this.factoryBeanAttribute = factoryBeanAttribute; + } + + public boolean hasFactoryMethodAttribute() { + return factoryMethodAttribute; + } + + public void setFactoryMethodAttribute(boolean factoryMethodAttribute) { + this.factoryMethodAttribute = factoryMethodAttribute; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("SpringBeanElement [id=").append(id).append(", className=").append(className) + .append(", innerBean=").append(innerBean).append(", abstractBean=").append(abstractBean) + .append(", parentAttribute=").append(parentAttribute).append(", factoryBeanAttribute=") + .append(factoryBeanAttribute).append(", factoryMethodAttribute=").append(factoryMethodAttribute) + .append(", properties=").append(properties).append(", constructorargs=").append(constructorargs) + .append("]"); + return builder.toString(); + } + +} // end class SpringBeanElement diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringConstructorArgElement.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringConstructorArgElement.java new file mode 100644 index 0000000000..1de0595d60 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringConstructorArgElement.java @@ -0,0 +1,90 @@ +/* + * 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.tuscany.sca.implementation.spring; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a <constructor-arg> element in a Spring application-context + * - this has ref attribute + * + * @version $Rev$ $Date$ + */ +public class SpringConstructorArgElement { + + private String type; + private int autoIndex = -1; + private int index = -1; + private List<String> refs = new ArrayList<String>(); + private List<String> values = new ArrayList<String>(); + + public SpringConstructorArgElement() { + + } + + public SpringConstructorArgElement(String type) { + this.type = type; + } + + public String getType() { + return this.type; + } + + public List<String> getRefs() { + return this.refs; + } + + public void addRef(String ref) { + this.refs.add(ref); + } + + public int getIndex() { + return this.index; + } + + public void setIndex(int index) { + this.index = index; + } + + public int getAutoIndex() { + return this.autoIndex; + } + + public void setAutoIndex(int index) { + this.autoIndex = index; + } + + public List<String> getValues() { + return this.values; + } + + public void addValue(String value) { + this.values.add(value); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("SpringConstructorArgElement [type=").append(type).append(", autoIndex=").append(autoIndex) + .append(", index=").append(index).append(", refs=").append(refs).append(", values=").append(values) + .append("]"); + return builder.toString(); + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementation.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementation.java new file mode 100644 index 0000000000..a5d4adb1bb --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementation.java @@ -0,0 +1,259 @@ +/* + * 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.tuscany.sca.implementation.spring; + +import java.net.URL; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentType; +import org.apache.tuscany.sca.assembly.Extensible; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.assembly.impl.ImplementationImpl; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; + +/** + * Represents a Spring implementation. + * + * @version $Rev$ $Date$ + */ +public class SpringImplementation extends ImplementationImpl implements Implementation, Extensible { + public final static QName TYPE = new QName(SCA11_NS, "implementation.spring"); + // The location attribute which points to the Spring application-context XML file + private String location; + // The application-context file as a Spring Resource + private List<URL> resource; + private ComponentType componentType; + // Mapping of Services to Beans + private Map<String, SpringBeanElement> serviceMap; + // Mapping of property names to Java class + private Map<String, Class<?>> propertyMap; + // List of unresolved bean property references + private Map<String, Reference> unresolvedBeanRef; + private ClassLoader classLoader; + + public SpringImplementation() { + super(TYPE); + this.location = null; + this.resource = null; + setUnresolved(true); + serviceMap = new HashMap<String, SpringBeanElement>(); + propertyMap = new HashMap<String, Class<?>>(); + unresolvedBeanRef = new HashMap<String, Reference>(); + } // end method SpringImplementation + + /* Returns the location attribute for this Spring implementation */ + public String getLocation() { + return location; + } + + /** + * Sets the location attribute for this Spring implementation + * location - a URI to the Spring application-context file + */ + public void setLocation(String location) { + this.location = location; + return; + } + + public void setResource(List<URL> resource) { + this.resource = resource; + } + + public List<URL> getResource() { + return resource; + } + + /* + * Returns the componentType for this Spring implementation + */ + public ComponentType getComponentType() { + return componentType; + } + + /* + * Sets the componentType for this Spring implementation + */ + public void setComponentType(ComponentType componentType) { + this.componentType = componentType; + } + + @Override + public List<Service> getServices() { + return componentType.getServices(); + } + + @Override + public List<Reference> getReferences() { + return componentType.getReferences(); + } + + @Override + public List<Property> getProperties() { + return componentType.getProperties(); + } + + /** + * Returns the Spring Bean which implements a particular service + * @param service the service + * @return the bean which implements the service, as a SpringBeanElement + */ + public SpringBeanElement getBeanFromService(Service service) { + SpringBeanElement theBean = serviceMap.get(service.getName()); + return theBean; + } + + /** + * Sets the mapping from a service to the Spring Bean that implements the service + * @param service the service + * @param theBean a SpringBeanElement for the Bean implementing the service + */ + public void setBeanForService(Service service, SpringBeanElement theBean) { + serviceMap.put(service.getName(), theBean); + } + + /** + * Add a mapping from a SCA property name to a Java class for the property + * @param propertyName + * @param propertyClass + */ + public void setPropertyClass(String propertyName, Class<?> propertyClass) { + if (propertyName == null || propertyClass == null) + return; + propertyMap.put(propertyName, propertyClass); + return; + } // end method setPropertyClass + + /** + * Gets the Java Class for an SCA property + * @param propertyName - the property name + * @return - a Class object for the type of the property + */ + public Class<?> getPropertyClass(String propertyName) { + return propertyMap.get(propertyName); + } // end method getPropertyClass + + public void setUnresolvedBeanRef(String refName, Reference reference) { + if (refName == null || reference == null) + return; + unresolvedBeanRef.put(refName, reference); + return; + } // end method setUnresolvedBeanRef + + public Reference getUnresolvedBeanRef(String refName) { + return unresolvedBeanRef.get(refName); + } // end method getUnresolvedBeanRef + + /** + * Use preProcess to validate and map the references and properties dynamically + */ + public void build(Component component) { + + for (Reference reference : component.getReferences()) { + if (unresolvedBeanRef.containsKey(reference.getName())) { + Reference ref = unresolvedBeanRef.get(reference.getName()); + componentType.getReferences().add(createReference(reference, ref.getInterfaceContract())); + unresolvedBeanRef.remove(reference.getName()); + } + } + + for (Property property : component.getProperties()) { + if (unresolvedBeanRef.containsKey(property.getName())) { + componentType.getProperties().add(createProperty(property)); + this.setPropertyClass(property.getName(), property.getClass()); + unresolvedBeanRef.remove(property.getName()); + } + } + } + + protected Reference createReference(Reference reference, InterfaceContract interfaze) { + Reference newReference; + try { + newReference = (Reference)reference.clone(); + if (newReference.getInterfaceContract() == null) + newReference.setInterfaceContract(interfaze); + } catch (CloneNotSupportedException e) { + throw new AssertionError(e); // should not ever happen + } + return newReference; + } + + protected Property createProperty(Property property) { + Property newProperty; + try { + newProperty = (Property)property.clone(); + } catch (CloneNotSupportedException e) { + throw new AssertionError(e); // should not ever happen + } + return newProperty; + } + + public ClassLoader getClassLoader() { + return classLoader; + } + + public void setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((location == null) ? 0 : location.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (!(obj instanceof SpringImplementation)) { + return false; + } + SpringImplementation other = (SpringImplementation)obj; + if (location == null) { + if (other.location != null) { + return false; + } + } else if (!location.equals(other.location)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("SpringImplementation [location=").append(location).append(", resource=").append(resource) + .append("]"); + return builder.toString(); + } +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementationBuilder.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementationBuilder.java new file mode 100644 index 0000000000..1a246fa03a --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementationBuilder.java @@ -0,0 +1,41 @@ +/* + * 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.tuscany.sca.implementation.spring; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.builder.BuilderContext; +import org.apache.tuscany.sca.assembly.builder.ImplementationBuilder; + +/** + * + */ +public class SpringImplementationBuilder implements ImplementationBuilder<SpringImplementation> { + + public void build(Component component, SpringImplementation implmentation, BuilderContext context) { + implmentation.build(component); + } + + public QName getImplementationType() { + return SpringImplementation.TYPE; + } + +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementationConstants.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementationConstants.java new file mode 100644 index 0000000000..27c09c1f18 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementationConstants.java @@ -0,0 +1,73 @@ +/* + * 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.tuscany.sca.implementation.spring; + +import javax.xml.namespace.QName; + +/** + * Constants used in Spring Application Context XML files. + */ +public interface SpringImplementationConstants { + + String SCA_NS = "http://www.springframework.org/schema/sca"; + String SPRING_NS = "http://www.springframework.org/schema/beans"; + + String PROPERTY = "property"; + QName SCA_PROPERTY_ELEMENT = new QName(SCA_NS, PROPERTY); + QName PROPERTY_ELEMENT = new QName(SPRING_NS, PROPERTY); + + String SCASERVICE = "service"; + QName SCA_SERVICE_ELEMENT = new QName(SCA_NS, SCASERVICE); + + String SCAREFERENCE = "reference"; + QName SCA_REFERENCE_ELEMENT = new QName(SCA_NS, SCAREFERENCE); + + String BEANS = "beans"; + QName BEANS_ELEMENT = new QName(SPRING_NS, BEANS); + + String IMPORT = "import"; + QName IMPORT_ELEMENT = new QName(SPRING_NS, IMPORT); + + String BEAN = "bean"; + QName BEAN_ELEMENT = new QName(SPRING_NS, BEAN); + + String CONSTRUCTORARG = "constructor-arg"; + QName CONSTRUCTORARG_ELEMENT = new QName(SPRING_NS, CONSTRUCTORARG); + + String LIST = "list"; + QName LIST_ELEMENT = new QName(SPRING_NS, LIST); + + String SET = "set"; + QName SET_ELEMENT = new QName(SPRING_NS, SET); + + String MAP = "map"; + QName MAP_ELEMENT = new QName(SPRING_NS, MAP); + + String VALUE = "value"; + QName VALUE_ELEMENT = new QName(SPRING_NS, VALUE); + + String REF = "ref"; + QName REF_ELEMENT = new QName(SPRING_NS, REF); + + String ENTRY = "entry"; + QName ENTRY_ELEMENT = new QName(SPRING_NS, ENTRY); + + String APPLICATION_CONTEXT = "application-context.xml"; +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringPropertyElement.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringPropertyElement.java new file mode 100644 index 0000000000..8de3a4cbe1 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringPropertyElement.java @@ -0,0 +1,71 @@ +/* + * 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.tuscany.sca.implementation.spring; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a <property> element in a Spring application-context + * - this has name and ref attributes + * + * @version $Rev$ $Date$ + */ +public class SpringPropertyElement { + + private String name; + private List<String> refs = new ArrayList<String>(); + private List<String> values = new ArrayList<String>(); + + public SpringPropertyElement() { + } + + public SpringPropertyElement(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public List<String> getRefs() { + return this.refs; + } + + public void addRef(String ref) { + this.refs.add(ref); + } + + public List<String> getValues() { + return this.values; + } + + public void addValue(String value) { + this.values.add(value); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("SpringPropertyElement [name=").append(name).append(", refs=").append(refs).append(", values=") + .append(values).append("]"); + return builder.toString(); + } + +} // end class SpringPropertyElement diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringSCAPropertyElement.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringSCAPropertyElement.java new file mode 100644 index 0000000000..f27506f28b --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringSCAPropertyElement.java @@ -0,0 +1,63 @@ +/* + * 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.tuscany.sca.implementation.spring; + +/** + * Represents an <sca:property> element in a Spring application-context + * - this has name and type attributes + * @version $Rev$ $Date$ + */ +public class SpringSCAPropertyElement { + + private String name; + private String type; + + public SpringSCAPropertyElement() { + super(); + } + + public SpringSCAPropertyElement(String name, String type) { + this.name = name; + this.type = type; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setType(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("SpringSCAPropertyElement [name=").append(name).append(", type=").append(type).append("]"); + return builder.toString(); + } + +} // end class SpringPropertyElement diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringSCAReferenceElement.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringSCAReferenceElement.java new file mode 100644 index 0000000000..74cd3f4290 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringSCAReferenceElement.java @@ -0,0 +1,92 @@ +/* + * 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.tuscany.sca.implementation.spring; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.PolicySet; + +/** + * Represents a <sca:reference> element in a Spring application-context + * - this has id and className attributes + * - plus zero or more property elements as children + * + * @version $Rev$ $Date$ + */ +public class SpringSCAReferenceElement { + + private String name; + private String type; + private String defaultBean; + private List<Intent> intents = new ArrayList<Intent>(); + private List<PolicySet> policySets = new ArrayList<PolicySet>(); + + public SpringSCAReferenceElement() { + + } + + public SpringSCAReferenceElement(String name, String type) { + this.name = name; + this.type = type; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setType(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + public void setDefaultBean(String defaultBean) { + this.defaultBean = defaultBean; + } + + public String getDefaultBean() { + return defaultBean; + } + + public List<Intent> getRequiredIntents() { + return intents; + } + + public List<PolicySet> getPolicySets() { + return policySets; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("SpringSCAReferenceElement [name=").append(name).append(", type=").append(type) + .append(", defaultBean=").append(defaultBean).append(", intents=").append(intents).append(", policySets=") + .append(policySets).append("]"); + return builder.toString(); + } + +} // end class SpringSCAReferenceElement diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringSCAServiceElement.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringSCAServiceElement.java new file mode 100644 index 0000000000..181bd7a787 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringSCAServiceElement.java @@ -0,0 +1,92 @@ +/* + * 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.tuscany.sca.implementation.spring; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.PolicySet; + +/** + * Represents a <sca:service> element in a Spring application-context + * - this has id and className attributes + * - plus zero or more property elements as children + * + * @version $Rev$ $Date$ + */ +public class SpringSCAServiceElement { + + private String name; + private String type; + private String target; + private List<Intent> intents = new ArrayList<Intent>(); + private List<PolicySet> policySets = new ArrayList<PolicySet>(); + + public SpringSCAServiceElement() { + + } + + public SpringSCAServiceElement(String name, String target) { + this.name = name; + this.target = target; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setType(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + public void setTarget(String target) { + this.target = target; + } + + public String getTarget() { + return target; + } + + public List<Intent> getRequiredIntents() { + return intents; + } + + public List<PolicySet> getPolicySets() { + return policySets; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("SpringSCAServiceElement [name=").append(name).append(", type=").append(type) + .append(", target=").append(target).append(", intents=").append(intents).append(", policySets=") + .append(policySets).append("]"); + return builder.toString(); + } + +} // end class SpringSCAServiceElement diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/introspect/SpringBeanIntrospector.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/introspect/SpringBeanIntrospector.java new file mode 100644 index 0000000000..5eaf27ab81 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/introspect/SpringBeanIntrospector.java @@ -0,0 +1,95 @@ +/* + * 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.tuscany.sca.implementation.spring.introspect; + +import java.util.List; + +import org.apache.tuscany.sca.assembly.ComponentType; +import org.apache.tuscany.sca.contribution.processor.ContributionResolveException; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.apache.tuscany.sca.implementation.spring.SpringConstructorArgElement; +import org.apache.tuscany.sca.implementation.spring.SpringImplementation; + +/** + * Provides introspection functions for Spring beans + * This version leans heavily on the implementation-java classes + * + * @version $Rev$ $Date$ + */ +public class SpringBeanIntrospector { + + private JavaImplementationFactory javaImplementationFactory; + + /** + * The constructor sets up the various visitor elements that will be used to introspect + * the Spring bean and extract SCA information. + * + * @param assemblyFactory The Assembly Factory to use + * @param javaFactory The Java Interface Factory to use + * @param policyFactory The Policy Factory to use. + */ + public SpringBeanIntrospector(ExtensionPointRegistry registry, List<SpringConstructorArgElement> conArgs) { + + FactoryExtensionPoint factories = registry.getExtensionPoint(FactoryExtensionPoint.class); + javaImplementationFactory = factories.getFactory(JavaImplementationFactory.class); + } // end constructor + + /** + * Introspect a Spring Bean and extract the features important to SCA + * @param beanClass the Spring Bean class to introspect + * @param componentType the componentType that is filled in through the introspection + * process (assumed empty on invocation, filled on return + * @return a Map of property names to JavaElementImpl + * @throws ContributionResolveException - if there was a problem resolving the + * Spring Bean or its componentType + * + */ + public JavaImplementation introspectBean(Class<?> beanClass, ComponentType componentType) + throws ContributionResolveException { + if (componentType == null) + throw new ContributionResolveException("Introspect Spring bean: supplied componentType is null"); + + // Create a Java implementation ready for the introspection + JavaImplementation javaImplementation = javaImplementationFactory.createJavaImplementation(); + // Set the type to be implementation.spring to avoid heuristic introspection + javaImplementation.setType(SpringImplementation.TYPE); + + try { + // Introspect the bean...the results of the introspection are placed into the Java implementation + javaImplementationFactory.createJavaImplementation(javaImplementation, beanClass); + + // Extract the services, references & properties found through introspection + // put the services, references and properties into the component type + componentType.getServices().addAll(javaImplementation.getServices()); + componentType.getReferences().addAll(javaImplementation.getReferences()); + componentType.getProperties().addAll(javaImplementation.getProperties()); + + } catch (IntrospectionException e) { + throw new ContributionResolveException(e); + } // end try + + return javaImplementation; + + } // end method introspectBean + +} // end class SpringBeanIntrospector diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/introspect/SpringXMLComponentTypeLoader.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/introspect/SpringXMLComponentTypeLoader.java new file mode 100644 index 0000000000..2730ee3146 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/introspect/SpringXMLComponentTypeLoader.java @@ -0,0 +1,917 @@ +/* + * 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.tuscany.sca.implementation.spring.introspect; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.jar.Attributes; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.Manifest; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.ComponentType; +import org.apache.tuscany.sca.assembly.Multiplicity; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.ContributionFactory; +import org.apache.tuscany.sca.contribution.processor.ContributionReadException; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.resolver.ClassReference; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.implementation.java.JavaConstructorImpl; +import org.apache.tuscany.sca.implementation.java.JavaElementImpl; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaParameterImpl; +import org.apache.tuscany.sca.implementation.spring.SpringBeanElement; +import org.apache.tuscany.sca.implementation.spring.SpringConstructorArgElement; +import org.apache.tuscany.sca.implementation.spring.SpringImplementation; +import org.apache.tuscany.sca.implementation.spring.SpringPropertyElement; +import org.apache.tuscany.sca.implementation.spring.SpringSCAPropertyElement; +import org.apache.tuscany.sca.implementation.spring.SpringSCAReferenceElement; +import org.apache.tuscany.sca.implementation.spring.SpringSCAServiceElement; +import org.apache.tuscany.sca.implementation.spring.xml.SpringXMLBeanDefinitionLoader; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.util.JavaXMLMapper; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; + +/** + * Introspects a Spring XML application-context configuration file to create <implementation-spring../> + * component type information. + * + * @version $Rev$ $Date$ + */ +public class SpringXMLComponentTypeLoader { + private final static Logger log = Logger.getLogger(SpringXMLComponentTypeLoader.class.getName()); + + private ExtensionPointRegistry registry; + private ContributionFactory contributionFactory; + private AssemblyFactory assemblyFactory; + private JavaInterfaceFactory javaFactory; + private SpringBeanIntrospector beanIntrospector; + + private SpringXMLBeanDefinitionLoader xmlBeanDefinitionLoader; + + public SpringXMLComponentTypeLoader(ExtensionPointRegistry registry) { + super(); + this.registry = registry; + FactoryExtensionPoint factories = registry.getExtensionPoint(FactoryExtensionPoint.class); + this.assemblyFactory = factories.getFactory(AssemblyFactory.class); + this.javaFactory = factories.getFactory(JavaInterfaceFactory.class); + this.contributionFactory = factories.getFactory(ContributionFactory.class); + this.xmlBeanDefinitionLoader = + registry.getExtensionPoint(UtilityExtensionPoint.class).getUtility(SpringXMLBeanDefinitionLoader.class); + } + + /** + * Report a error. + * + * @param problems + * @param message + * @param model + */ + private void error(Monitor monitor, String message, Object model, Object... messageParameters) { + if (monitor != null) { + Problem problem = + monitor.createProblem(this.getClass().getName(), + "impl-spring-validation-messages", + Severity.ERROR, + model, + message, + (Object[])messageParameters); + monitor.problem(problem); + } + } + + protected Class<SpringImplementation> getImplementationClass() { + return SpringImplementation.class; + } + + /** + * Base method which loads the component type from the application-context attached to the + * Spring implementation + * + */ + public void load(SpringImplementation implementation, ModelResolver resolver, ProcessorContext context) + throws ContributionReadException { + //System.out.println("Spring TypeLoader - load method start"); + ComponentType componentType = implementation.getComponentType(); + /* Check that there is a component type object already set */ + if (componentType == null) { + throw new ContributionReadException("SpringXMLLoader load: implementation has no ComponentType object"); + } + if (componentType.isUnresolved()) { + /* Fetch the location of the application-context file from the implementation */ + loadFromXML(implementation, resolver, context); + if (!componentType.isUnresolved()) + implementation.setUnresolved(false); + } // end if + //System.out.println("Spring TypeLoader - load method complete"); + } // end method load + + private Class<?> resolveClass(ModelResolver resolver, String className, ProcessorContext context) + throws ClassNotFoundException { + ClassReference classReference = new ClassReference(className); + classReference = resolver.resolveModel(ClassReference.class, classReference, context); + if (classReference.isUnresolved()) { + throw new ClassNotFoundException(className); + } + Class<?> javaClass = classReference.getJavaClass(); + return javaClass; + } + + /** + * Method which fills out the component type for a Spring implementation by reading the + * Spring application-context.xml file. + * + * @param implementation SpringImplementation into which to load the component type information + * @throws ContributionReadException Failed to read the contribution + */ + private void loadFromXML(SpringImplementation implementation, ModelResolver resolver, ProcessorContext context) + throws ContributionReadException { + List<SpringBeanElement> beans = new ArrayList<SpringBeanElement>(); + List<SpringSCAServiceElement> services = new ArrayList<SpringSCAServiceElement>(); + List<SpringSCAReferenceElement> references = new ArrayList<SpringSCAReferenceElement>(); + List<SpringSCAPropertyElement> scaproperties = new ArrayList<SpringSCAPropertyElement>(); + + URL resource; + List<URL> contextResources = new ArrayList<URL>(); + String contextPath = implementation.getLocation(); + + try { + resource = resolveLocation(resolver, contextPath, context); + contextResources = getApplicationContextResource(resource); + + implementation.setClassLoader(new ContextClassLoader(resolver, context)); + implementation.setResource(contextResources); + // The URI is used to uniquely identify the Implementation + implementation.setURI(resource.toString()); + + List<SpringBeanElement> appCxtBeans = new ArrayList<SpringBeanElement>(); + List<SpringSCAServiceElement> appCxtServices = new ArrayList<SpringSCAServiceElement>(); + List<SpringSCAReferenceElement> appCxtReferences = new ArrayList<SpringSCAReferenceElement>(); + List<SpringSCAPropertyElement> appCxtProperties = new ArrayList<SpringSCAPropertyElement>(); + + if (xmlBeanDefinitionLoader != null) { + xmlBeanDefinitionLoader.load(contextResources, + appCxtServices, + appCxtReferences, + appCxtProperties, + appCxtBeans, + context); + } + // Validate the beans from individual application context for uniqueness + validateBeans(appCxtBeans, appCxtServices, appCxtReferences, appCxtProperties, context.getMonitor()); + // Add all the validated beans to the generic list + beans.addAll(appCxtBeans); + services.addAll(appCxtServices); + references.addAll(appCxtReferences); + scaproperties.addAll(appCxtProperties); + } catch (Throwable e) { + throw new ContributionReadException(e); + } + + /* At this point, the complete application-context.xml file has been read and its contents */ + /* stored in the lists of beans, services, references. These are now used to generate */ + /* the implied componentType for the application context */ + generateComponentType(implementation, resolver, beans, services, references, scaproperties, context); + + return; + } // end method loadFromXML + + private URL resolveLocation(ModelResolver resolver, String contextPath, ProcessorContext context) + throws MalformedURLException, ContributionReadException { + URL resource = null; + URI uri = URI.create(contextPath); + if (!uri.isAbsolute()) { + Artifact parent = context.getArtifact(); + if (parent != null && parent.getURI() != null) { + URI base = URI.create("/" + parent.getURI()); + uri = base.resolve(uri); + // Remove the leading / to make artifact resolver happy + if (uri.toString().startsWith("/")) { + uri = URI.create(uri.toString().substring(1)); + } + } + Artifact artifact = contributionFactory.createArtifact(); + artifact.setUnresolved(true); + artifact.setURI(uri.toString()); + artifact = resolver.resolveModel(Artifact.class, artifact, context); + if (!artifact.isUnresolved()) { + resource = new URL(artifact.getLocation()); + } else { + throw new ContributionReadException("Location cannot be resloved: " + contextPath); + } + } else { + resource = new URL(contextPath); + } + return resource; + } + + /** + * Generates the Spring implementation component type from the configuration contained in the + * lists of beans, services, references and scaproperties derived from the application context + */ + private void generateComponentType(SpringImplementation implementation, + ModelResolver resolver, + List<SpringBeanElement> beans, + List<SpringSCAServiceElement> services, + List<SpringSCAReferenceElement> references, + List<SpringSCAPropertyElement> scaproperties, + ProcessorContext context) throws ContributionReadException { + /* + * 1. Each sca:service becomes a service in the component type + * 2. Each sca:reference becomes a reference in the component type + * 3. Each sca:property becomes a property in the component type + * 4. IF there are no explicit service elements, each bean becomes a service + * 5. Each bean property which is a reference not pointing at another bean in the + * application context becomes a reference unless it is pointing at one of the references + * 6. Each bean property which is not a reference and which is not pointing + * at another bean in the application context becomes a property in the component type + */ + + JavaImplementation javaImplementation = null; + ComponentType componentType = implementation.getComponentType(); + + try { + // Deal with the services first.... + Iterator<SpringSCAServiceElement> its = services.iterator(); + while (its.hasNext()) { + SpringSCAServiceElement serviceElement = its.next(); + Class<?> interfaze = resolveClass(resolver, serviceElement.getType(), context); + Service theService = createService(interfaze, serviceElement.getName()); + // Spring allows duplication of bean definitions in multiple context scenario, + // in such cases, the latest bean definition overrides the older ones, hence + // we will remove any older definition and use the latest. + Service duplicate = null; + for (Service service : componentType.getServices()) { + if (service.getName().equals(theService.getName())) + duplicate = service; + } + if (duplicate != null) + componentType.getServices().remove(duplicate); + + componentType.getServices().add(theService); + // Add this service to the Service / Bean map + String beanName = serviceElement.getTarget(); + for (SpringBeanElement beanElement : beans) { + if (beanName.equals(beanElement.getId())) { + if (isValidBeanForService(beanElement)) { + // add the required intents and policySets for the service + theService.getRequiredIntents().addAll(serviceElement.getRequiredIntents()); + theService.getPolicySets().addAll(serviceElement.getPolicySets()); + implementation.setBeanForService(theService, beanElement); + } + } + } // end for + } // end while + + // Next handle the references + Iterator<SpringSCAReferenceElement> itr = references.iterator(); + while (itr.hasNext()) { + SpringSCAReferenceElement referenceElement = itr.next(); + Class<?> interfaze = resolveClass(resolver, referenceElement.getType(), context); + Reference theReference = createReference(interfaze, referenceElement.getName()); + // Override the older bean definition with the latest ones + // for the duplicate definitions found. + Reference duplicate = null; + for (Reference reference : componentType.getReferences()) { + if (reference.getName().equals(theReference.getName())) + duplicate = reference; + } + if (duplicate != null) + componentType.getReferences().remove(duplicate); + + // add the required intents and policySets for this reference + theReference.getRequiredIntents().addAll(referenceElement.getRequiredIntents()); + theReference.getPolicySets().addAll(referenceElement.getPolicySets()); + componentType.getReferences().add(theReference); + } // end while + + // Next handle the properties + Iterator<SpringSCAPropertyElement> itsp = scaproperties.iterator(); + while (itsp.hasNext()) { + SpringSCAPropertyElement scaproperty = itsp.next(); + // Create a component type property if the SCA property element has a name + // and a type declared... + if (scaproperty.getType() != null && scaproperty.getName() != null) { + Property theProperty = assemblyFactory.createProperty(); + theProperty.setName(scaproperty.getName()); + // Get the Java class and then an XSD element type for the property + Class<?> propType = Class.forName(scaproperty.getType()); + theProperty.setXSDType(JavaXMLMapper.getXMLType(propType)); + // Override the older bean definition with the latest ones + // for the duplicate definitions found. + Property duplicate = null; + for (Property property : componentType.getProperties()) { + if (property.getName().equals(theProperty.getName())) + duplicate = property; + } + if (duplicate != null) + componentType.getProperties().remove(duplicate); + + componentType.getProperties().add(theProperty); + // Remember the Java Class (ie the type) for this property + implementation.setPropertyClass(theProperty.getName(), propType); + } // end if + } // end while + + // Finally deal with the beans + Iterator<SpringBeanElement> itb; + // If there are no explicit service elements, then expose all the beans + if (services.isEmpty()) { + itb = beans.iterator(); + // Loop through all the beans found + while (itb.hasNext()) { + SpringBeanElement beanElement = itb.next(); + + // If its not a valid bean for service, ignore it + if (!isValidBeanForService(beanElement)) { + continue; + } + try { + // Load the Spring bean class + Class<?> beanClass = resolveClass(resolver, beanElement.getClassName(), context); + // Introspect the bean + beanIntrospector = new SpringBeanIntrospector(registry, beanElement.getCustructorArgs()); + ComponentType beanComponentType = assemblyFactory.createComponentType(); + javaImplementation = beanIntrospector.introspectBean(beanClass, beanComponentType); + // Set the service name as bean name + for (Service componentService : beanComponentType.getServices()) { + componentService.setName(beanElement.getId()); + } + // Get the service interface defined by this Spring Bean and add to + // the component type of the Spring Assembly + List<Service> beanServices = beanComponentType.getServices(); + componentType.getServices().addAll(beanServices); + // Add these services to the Service / Bean map + for (Service beanService : beanServices) { + implementation.setBeanForService(beanService, beanElement); + } + } catch (Throwable e) { + // [rfeng] FIXME: Some Spring beans have constructors that take pararemters injected by Spring and + // Tuscany is not happy with that during the introspection + log.log(Level.SEVERE, e.getMessage(), e); + } + } // end while + } // end if + + itb = beans.iterator(); + while (itb.hasNext()) { + SpringBeanElement beanElement = itb.next(); + + // If its not a valid bean for service, ignore it + if (!isValidBeanForService(beanElement)) { + continue; + } + // Ignore if the bean has no properties and constructor arguments + if (beanElement.getProperties().isEmpty() && beanElement.getCustructorArgs().isEmpty()) + continue; + + ComponentType beanComponentType = assemblyFactory.createComponentType(); + + try { + Class<?> beanClass = resolveClass(resolver, beanElement.getClassName(), context); + // Introspect the bean + beanIntrospector = new SpringBeanIntrospector(registry, beanElement.getCustructorArgs()); + javaImplementation = beanIntrospector.introspectBean(beanClass, beanComponentType); + } catch (Exception e) { + // [rfeng] FIXME: Some Spring beans have constructors that take pararemters injected by Spring and + // Tuscany is not happy with that during the introspection + log.log(Level.SEVERE, e.getMessage(), e); + continue; + } + Map<String, JavaElementImpl> propertyMap = javaImplementation.getPropertyMembers(); + JavaConstructorImpl constructor = javaImplementation.getConstructor(); + // Get the references by this Spring Bean and add the unresolved ones to + // the component type of the Spring Assembly + List<Reference> beanReferences = beanComponentType.getReferences(); + List<Property> beanProperties = beanComponentType.getProperties(); + + Set<String> excludedNames = new HashSet<String>(); + Iterator<SpringPropertyElement> itp = beanElement.getProperties().iterator(); + while (itp.hasNext()) { + SpringPropertyElement propertyElement = itp.next(); + // Exclude the reference that is also known as a spring property + excludedNames.add(propertyElement.getName()); + for (String propertyRef : propertyElement.getRefs()) { + if (propertyRefUnresolved(propertyRef, beans, references, scaproperties)) { + // This means an unresolved reference from the spring bean... + for (Reference reference : beanReferences) { + if (propertyElement.getName().equals(reference.getName())) { + // The name of the reference in this case is the string in + // the @ref attribute of the Spring property element, NOT the + // name of the field in the Spring bean.... + reference.setName(propertyRef); + componentType.getReferences().add(reference); + break; + } // end if + } // end for + + // Store the unresolved references as unresolvedBeanRef in the Spring Implementation type + for (Property scaproperty : beanProperties) { + if (propertyElement.getName().equals(scaproperty.getName())) { + // The name of the reference in this case is the string in + // the @ref attribute of the Spring property element, NOT the + // name of the field in the Spring bean.... + Class<?> interfaze = + resolveClass(resolver, + (propertyMap.get(propertyElement.getName()).getType()).getName(), + context); + Reference theReference = createReference(interfaze, propertyRef); + implementation.setUnresolvedBeanRef(propertyRef, theReference); + break; + } // end if + } // end for + } // end if + } // end for + } // end while + + Iterator<SpringConstructorArgElement> itcr = beanElement.getCustructorArgs().iterator(); + while (itcr.hasNext()) { + SpringConstructorArgElement conArgElement = itcr.next(); + for (String constructorArgRef : conArgElement.getRefs()) { + if (propertyRefUnresolved(constructorArgRef, beans, references, scaproperties)) { + for (JavaParameterImpl parameter : constructor.getParameters()) { + String paramType = parameter.getType().getName(); + Class<?> interfaze = resolveClass(resolver, paramType, context); + // Create a component type reference/property if the constructor-arg element has a + // type attribute OR index attribute declared... + if ((conArgElement.getType() != null && paramType.equals(conArgElement.getType())) || (conArgElement + .getIndex() != -1 && (conArgElement.getIndex() == parameter.getIndex()))) { + // [rfeng] Commenting out the following code as the constructor parameter based SCA + // references are added already + /* + if (parameter.getClassifer() == org.oasisopen.sca.annotation.Reference.class) { + Reference theReference = createReference(interfaze, constructorArgRef); + componentType.getReferences().add(theReference); + } + */ + if (parameter.getClassifer() == org.oasisopen.sca.annotation.Property.class) { + // Store the unresolved references as unresolvedBeanRef in the Spring Implementation type + // we might need to verify with the component definition later. + Reference theReference = createReference(interfaze, constructorArgRef); + implementation.setUnresolvedBeanRef(constructorArgRef, theReference); + } + } + } // end for + } // end if + } // end for + } // end while + + // [rfeng] Add the remaining introspected references (w/ @Reference but without Spring property ref) + for (Reference ref : beanReferences) { + if (!excludedNames.contains(ref.getName()) && componentType.getReference(ref.getName()) == null) { + // Only add the ones that not listed by sca:reference + componentType.getReferences().add(ref); + } + } + + } // end while + + } catch (ClassNotFoundException e) { + // Means that either an interface class, property class or a bean was not found + throw new ContributionReadException(e); + } catch (InvalidInterfaceException e) { + throw new ContributionReadException(e); + } // end try + + // If we get here, the Spring assembly component type is resolved + componentType.setUnresolved(false); + implementation.setComponentType(componentType); + return; + } // end method generateComponentType + + /* + * Determines whether a reference attribute of a Spring property element is resolved either + * by a bean in the application context or by an SCA reference element or by an SCA property + * element + * @param ref - a String containing the name of the reference - may be null + * @param beans - a List of SpringBean elements + * @param references - a List of SCA reference elements + * @return true if the property is not resolved, false if it is resolved + */ + private boolean propertyRefUnresolved(String ref, + List<SpringBeanElement> beans, + List<SpringSCAReferenceElement> references, + List<SpringSCAPropertyElement> scaproperties) { + boolean unresolved = true; + + if (ref != null) { + // Scan over the beans looking for a match + Iterator<SpringBeanElement> itb = beans.iterator(); + while (itb.hasNext()) { + SpringBeanElement beanElement = itb.next(); + // Does the bean name match the ref? + if (ref.equals(beanElement.getId())) { + unresolved = false; + break; + } // end if + } // end while + // Scan over the SCA reference elements looking for a match + if (unresolved) { + Iterator<SpringSCAReferenceElement> itr = references.iterator(); + while (itr.hasNext()) { + SpringSCAReferenceElement referenceElement = itr.next(); + if (ref.equals(referenceElement.getName())) { + unresolved = false; + break; + } // end if + } // end while + } // end if + // Scan over the SCA property elements looking for a match + if (unresolved) { + Iterator<SpringSCAPropertyElement> itsp = scaproperties.iterator(); + while (itsp.hasNext()) { + SpringSCAPropertyElement propertyElement = itsp.next(); + if (ref.equals(propertyElement.getName())) { + unresolved = false; + break; + } // end if + } // end while + } // end if + } else { + // In the case where ref = null, the property is not going to be a reference of any + // kind and can be ignored + unresolved = false; + } // end if + + return unresolved; + + } // end method propertyRefUnresolved + + /** + * Validates whether the <sca:service>, <sca:reference> and <sca:property> elements + * has unique names within the application context. + */ + private void validateBeans(List<SpringBeanElement> beans, + List<SpringSCAServiceElement> services, + List<SpringSCAReferenceElement> references, + List<SpringSCAPropertyElement> scaproperties, + Monitor monitor) throws ContributionReadException { + + // The @target attribute of a <service/> subelement of a <beans/> element + // MUST have the value of the @name attribute of one of the <bean/> + // subelements of the <beans/> element. + Iterator<SpringSCAServiceElement> its = services.iterator(); + while (its.hasNext()) { + SpringSCAServiceElement serviceElement = its.next(); + boolean targetBeanExists = false; + Iterator<SpringBeanElement> itb = beans.iterator(); + while (itb.hasNext()) { + SpringBeanElement beanElement = itb.next(); + if (serviceElement.getTarget().equals(beanElement.getId())) + targetBeanExists = true; + } + if (!targetBeanExists) + error(monitor, "TargetBeanDoesNotExist", beans); + } // end while + + // The value of the @name attribute of an <sca:reference/> subelement of a <beans/> + // element MUST be unique amongst the @name attributes of the <sca:property/> + // subelements and the <bean/> subelements of the <beans/> element. + // AND + // The @default attribute of a <sca:reference/> subelement of a <beans/> + // element MUST have the value of the @name attribute of one of the <bean/> + // subelements of the <beans/> element. + Iterator<SpringSCAReferenceElement> itr = references.iterator(); + while (itr.hasNext()) { + SpringSCAReferenceElement referenceElement = itr.next(); + boolean defaultBeanExists = true; + boolean isUniqueReferenceName = true; + Iterator<SpringBeanElement> itb = beans.iterator(); + while (itb.hasNext()) { + SpringBeanElement beanElement = itb.next(); + if (referenceElement.getDefaultBean() != null) + if (referenceElement.getDefaultBean().equals(beanElement.getId())) + defaultBeanExists = false; + if (referenceElement.getName().equals(beanElement.getId())) + isUniqueReferenceName = false; + } + Iterator<SpringSCAPropertyElement> itp = scaproperties.iterator(); + while (itp.hasNext()) { + SpringSCAPropertyElement propertyElement = itp.next(); + if (referenceElement.getName().equals(propertyElement.getName())) + isUniqueReferenceName = false; + } + if (!defaultBeanExists) + error(monitor, "DefaultBeanDoesNotExist", beans); + if (!isUniqueReferenceName) + error(monitor, "ScaReferenceNameNotUnique", beans); + } // end while + + // The value of the @name attribute of an <sca:property/> subelement of a <beans/> + // element MUST be unique amongst the @name attributes of the <sca:reference/> + // subelements and the <bean/> subelements of the <beans/> element. + Iterator<SpringSCAPropertyElement> itp = scaproperties.iterator(); + while (itp.hasNext()) { + SpringSCAPropertyElement propertyElement = itp.next(); + boolean isUniquePropertyName = true; + Iterator<SpringBeanElement> itb = beans.iterator(); + while (itb.hasNext()) { + SpringBeanElement beanElement = itb.next(); + if (propertyElement.getName().equals(beanElement.getId())) + isUniquePropertyName = false; + } + Iterator<SpringSCAReferenceElement> itrp = references.iterator(); + while (itrp.hasNext()) { + SpringSCAReferenceElement referenceElement = itrp.next(); + if (propertyElement.getName().equals(referenceElement.getName())) + isUniquePropertyName = false; + } + if (!isUniquePropertyName) + error(monitor, "ScaPropertyNameNotUnique", beans); + } // end while + } + + /** + * Validates whether a bean definition is valid for exposing as service. + */ + private boolean isValidBeanForService(SpringBeanElement beanElement) { + + if (beanElement.isInnerBean()) + return false; + if (beanElement.hasParentAttribute()) + return false; + if (beanElement.hasFactoryMethodAttribute()) + return false; + if (beanElement.hasFactoryBeanAttribute()) + return false; + if (beanElement.getClassName() == null) + return false; + if (beanElement.getClassName().startsWith("org.springframework")) + return false; + // return true otherwise + return true; + } + + /** + * Gets hold of the application-context.xml file as a Spring resource + * @param locationAttr - the location attribute from the <implementation.spring../> element + * @param cl - the ClassLoader for the Spring implementation + */ + protected List<URL> getApplicationContextResource(URL url) throws ContributionReadException { + File manifestFile = null; + File appXmlFile; + File appXmlFolder; + File locationFile = null; + List<URL> appCtxResources = new ArrayList<URL>(); + + if (url != null) { + String path = url.getPath(); + locationFile = new File(path); + } else { + throw new ContributionReadException( + "SpringXMLComponentTypeLoader getApplicationContextResource: " + "unable to find resource file " + + url); + } + + if (locationFile.isDirectory()) { + try { + manifestFile = new File(locationFile, "META-INF" + File.separator + "MANIFEST.MF"); + if (manifestFile.exists()) { + Manifest mf = new Manifest(new FileInputStream(manifestFile)); + Attributes mainAttrs = mf.getMainAttributes(); + String appCtxPath = mainAttrs.getValue("Spring-Context"); + if (appCtxPath != null) { + String[] cxtPaths = appCtxPath.split(";"); + for (String path : cxtPaths) { + appXmlFile = new File(locationFile, path.trim()); + if (appXmlFile.exists()) { + appCtxResources.add(appXmlFile.toURI().toURL()); + } + } + return appCtxResources; + } + } + // No MANIFEST.MF file OR no manifest-specified Spring context , then read all the + // xml files available in the META-INF/spring folder. + appXmlFolder = new File(locationFile, "META-INF" + File.separator + "spring"); + if (appXmlFolder.exists()) { + File[] files = appXmlFolder.listFiles(); + for (File appFile : files) { + if (appFile.getName().endsWith(".xml")) { + appCtxResources.add(appFile.toURI().toURL()); + } + } + return appCtxResources; + } + } catch (IOException e) { + throw new ContributionReadException("Error reading manifest " + manifestFile); + } + } else { + if (locationFile.isFile() && locationFile.getName().endsWith(".jar")) { + try { + JarFile jf = new JarFile(locationFile); + JarEntry je; + Manifest mf = jf.getManifest(); + if (mf != null) { + Attributes mainAttrs = mf.getMainAttributes(); + String appCtxPath = mainAttrs.getValue("Spring-Context"); + if (appCtxPath != null) { + String[] cxtPaths = appCtxPath.split(";"); + for (String path : cxtPaths) { + je = jf.getJarEntry(path.trim()); + if (je != null) + appCtxResources.add(new URL("jar:" + locationFile.toURI().toURL() + + "!/" + + appCtxPath)); + } + return appCtxResources; + } + } + // No MANIFEST.MF file OR no manifest-specified Spring context , then read all the + // .xml files available in the META-INF/spring folder. + Enumeration<JarEntry> entries = jf.entries(); + while (entries.hasMoreElements()) { + je = entries.nextElement(); + if (je.getName().startsWith("META-INF/spring/") && je.getName().endsWith(".xml")) { + appCtxResources.add(new URL("jar:" + locationFile.toURI().toURL() + "!/" + je.getName())); + } + } + return appCtxResources; + } catch (IOException e) { + // TODO: create a more appropriate exception type + throw new ContributionReadException( + "SpringXMLComponentTypeLoader getApplicationContextResource: " + " IO exception reading context file.", + e); + } + } else { + if (locationFile.getName().endsWith(".xml")) { + appCtxResources.add(url); + return appCtxResources; + } else { + // Deal with the directory inside a jar file, in case the contribution itself is a JAR file. + try { + if (locationFile.getPath().indexOf(".jar") > 0) { + String jarPath = url.getPath().substring(5, url.getPath().indexOf("!")); + JarFile jf = new JarFile(jarPath); + JarEntry je = + jf.getJarEntry(url.getPath().substring(url.getPath().indexOf("!/") + 2) + "/" + + "META-INF" + + "/" + + "MANIFEST.MF"); + if (je != null) { + Manifest mf = new Manifest(jf.getInputStream(je)); + Attributes mainAttrs = mf.getMainAttributes(); + String appCtxPath = mainAttrs.getValue("Spring-Context"); + if (appCtxPath != null) { + String[] cxtPaths = appCtxPath.split(";"); + for (String path : cxtPaths) { + je = + jf.getJarEntry(url.getPath().substring(url.getPath().indexOf("!/") + 2) + "/" + + path.trim()); + if (je != null) { + appCtxResources.add(new URL("jar:" + url.getPath() + "/" + path.trim())); + } + } + return appCtxResources; + } + } + // No MANIFEST.MF file OR no manifest-specified Spring context , then read all the + // .xml files available in the META-INF/spring folder. + Enumeration<JarEntry> entries = jf.entries(); + while (entries.hasMoreElements()) { + je = entries.nextElement(); + if (je.getName().startsWith("META-INF/spring/") && je.getName().endsWith(".xml")) { + appCtxResources.add(new URL("jar:" + url.getPath() + "/" + je.getName())); + } + } + return appCtxResources; + } + } catch (IOException e) { + throw new ContributionReadException("Error reading manifest " + manifestFile); + } + } + } + } + + throw new ContributionReadException( + "SpringXMLComponentTypeLoader getApplicationContextResource: " + "unable to read resource file " + + url); + } // end method getApplicationContextResource + + /** + * Creates a Service for the component type based on its name and Java interface + */ + public Service createService(Class<?> interfaze, String name) throws InvalidInterfaceException { + Service service = assemblyFactory.createService(); + JavaInterfaceContract interfaceContract = javaFactory.createJavaInterfaceContract(); + service.setInterfaceContract(interfaceContract); + + // Set the name for the service + service.setName(name); + + // Set the call interface and, if present, the callback interface + JavaInterface callInterface = javaFactory.createJavaInterface(interfaze); + service.getInterfaceContract().setInterface(callInterface); + if (callInterface.getCallbackClass() != null) { + JavaInterface callbackInterface = javaFactory.createJavaInterface(callInterface.getCallbackClass()); + service.getInterfaceContract().setCallbackInterface(callbackInterface); + } + return service; + } // end method createService + + /** + * Creates a Reference for the component type based on its name and Java interface + */ + private org.apache.tuscany.sca.assembly.Reference createReference(Class<?> interfaze, String name) + throws InvalidInterfaceException { + org.apache.tuscany.sca.assembly.Reference reference = assemblyFactory.createReference(); + JavaInterfaceContract interfaceContract = javaFactory.createJavaInterfaceContract(); + reference.setInterfaceContract(interfaceContract); + + // Set the name of the reference to the supplied name and the multiplicity of the reference + // to 1..1 - for Spring implementations, this is the only multiplicity supported + reference.setName(name); + reference.setMultiplicity(Multiplicity.ONE_ONE); + + // Set the call interface and, if present, the callback interface + JavaInterface callInterface = javaFactory.createJavaInterface(interfaze); + reference.getInterfaceContract().setInterface(callInterface); + if (callInterface.getCallbackClass() != null) { + JavaInterface callbackInterface = javaFactory.createJavaInterface(callInterface.getCallbackClass()); + reference.getInterfaceContract().setCallbackInterface(callbackInterface); + } + + return reference; + } + + private class ContextClassLoader extends ClassLoader { + public ContextClassLoader(ModelResolver resolver, ProcessorContext context) { + super(); + this.resolver = resolver; + this.context = context; + } + + private ModelResolver resolver; + private ProcessorContext context; + + @Override + protected Class<?> findClass(String name) throws ClassNotFoundException { + return SpringXMLComponentTypeLoader.this.resolveClass(resolver, name, context); + } + + @Override + protected URL findResource(String name) { + try { + return resolveLocation(resolver, name, context); + } catch (Exception e) { + return null; + } + } + + @Override + protected Enumeration<URL> findResources(String name) throws IOException { + URL url = findResource(name); + if (url != null) { + return Collections.enumeration(Arrays.asList(url)); + } else { + Collection<URL> urls = Collections.emptyList(); + return Collections.enumeration(urls); + } + } + } +} // end class SpringXMLComponentTypeLoader diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringImplementationProcessor.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringImplementationProcessor.java new file mode 100644 index 0000000000..4b4144f0c8 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringImplementationProcessor.java @@ -0,0 +1,244 @@ +/* + * 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.tuscany.sca.implementation.spring.xml; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.ComponentType; +import org.apache.tuscany.sca.assembly.xml.Constants; +import org.apache.tuscany.sca.assembly.xml.PolicySubjectProcessor; +import org.apache.tuscany.sca.contribution.processor.BaseStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.ContributionReadException; +import org.apache.tuscany.sca.contribution.processor.ContributionResolveException; +import org.apache.tuscany.sca.contribution.processor.ContributionWriteException; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.implementation.spring.SpringImplementation; +import org.apache.tuscany.sca.implementation.spring.introspect.SpringXMLComponentTypeLoader; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; + +/** + * SpringArtifactProcessor is responsible for processing the XML of an <implementation.spring.../> + * element in an SCA SCDL file. + * + * @version $Rev$ $Date$ + */ +public class SpringImplementationProcessor extends BaseStAXArtifactProcessor implements + StAXArtifactProcessor<SpringImplementation> { + + private static final String LOCATION = "location"; + private static final String IMPLEMENTATION_SPRING = "implementation.spring"; + private static final QName IMPLEMENTATION_SPRING_QNAME = new QName(Constants.SCA11_NS, IMPLEMENTATION_SPRING); + private static final String MSG_LOCATION_MISSING = "Reading implementation.spring - location attribute missing"; + + private ExtensionPointRegistry registry; + private AssemblyFactory assemblyFactory; + private PolicySubjectProcessor policyProcessor; + + private FactoryExtensionPoint factories; + + public SpringImplementationProcessor(ExtensionPointRegistry registry) { + this.registry = registry; + this.factories = registry.getExtensionPoint(FactoryExtensionPoint.class); + this.assemblyFactory = factories.getFactory(AssemblyFactory.class); + this.policyProcessor = new PolicySubjectProcessor(registry); + } + + /** + * Report a exception. + * + * @param problems + * @param message + * @param model + */ + private void error(Monitor monitor, String message, Object model, Exception ex) { + if (monitor != null) { + Problem problem = + monitor.createProblem(this.getClass().getName(), + "impl-spring-validation-messages", + Severity.ERROR, + model, + message, + ex); + monitor.problem(problem); + } + } + + /** + * Report a error. + * + * @param problems + * @param message + * @param model + */ + private void error(Monitor monitor, String message, Object model, Object... messageParameters) { + if (monitor != null) { + Problem problem = + monitor.createProblem(this.getClass().getName(), + "impl-spring-validation-messages", + Severity.ERROR, + model, + message, + (Object[])messageParameters); + monitor.problem(problem); + } + } + + /* + * Read the XML and parse out the attributes. + * + * <implementation.spring.../> has a single required attribute: + * "location" - which is the target URI of of an archive file or a directory that contains the Spring + * application context files. + * If the resource identified by the location attribute is an archive file, then the file + * META-INF/MANIFEST.MF is read from the archive. + * If the location URI identifies a directory, then META-INF/MANIFEST.MF must exist + * underneath that directory. + * If the manifest file contains a header "Spring-Context" of the format: + * Spring-Context ::= path ( ';' path )* + * + * Where path is a relative path with respect to the location URI, then the set of paths + * specified in the header identify the context configuration files. + * If there is no MANIFEST.MF file or no Spring-Context header within that file, + * then the default behaviour is to build an application context using all the *.xml files + * in the META-INF/spring directory. + */ + public SpringImplementation read(XMLStreamReader reader, ProcessorContext context) + throws ContributionReadException, XMLStreamException { + + // Create the Spring implementation + SpringImplementation springImplementation = null; + + // Read the location attribute for the spring implementation + String springLocation = getURIString(reader, LOCATION); + if (springLocation != null) { + springImplementation = new SpringImplementation(); + springImplementation.setLocation(springLocation); + springImplementation.setUnresolved(true); + processComponentType(springImplementation); + } else { + error(context.getMonitor(), "LocationAttributeMissing", reader); + //throw new ContributionReadException(MSG_LOCATION_MISSING); + } + + // Read policies + policyProcessor.readPolicies(springImplementation, reader); + + // Skip to end element + while (reader.hasNext()) { + if (reader.next() == END_ELEMENT && IMPLEMENTATION_SPRING_QNAME.equals(reader.getName())) { + break; + } + } // end while + + return springImplementation; + } // end read + + /* + * Handles the component type for the Spring implementation + * @param springImplementation - a Spring implementation. The component type information + * is created for this implementation + * + */ + private void processComponentType(SpringImplementation springImplementation) { + + // Create a ComponentType and mark it unresolved + ComponentType componentType = assemblyFactory.createComponentType(); + componentType.setUnresolved(true); + springImplementation.setComponentType(componentType); + } // end processComponentType + + /* + * Write out the XML representation of the Spring implementation + * <implementation.spring location="..." /> + */ + public void write(SpringImplementation springImplementation, XMLStreamWriter writer, ProcessorContext context) + throws ContributionWriteException, XMLStreamException { + + // Write <implementation.spring> + writer.writeStartElement(Constants.SCA11_NS, IMPLEMENTATION_SPRING); + policyProcessor.writePolicyAttributes(springImplementation, writer); + + if (springImplementation.getLocation() != null) { + writer.writeAttribute(LOCATION, springImplementation.getLocation()); + } + + writer.writeEndElement(); + + } // end write + + /** + * Resolves the Spring implementation - loads the Spring application-context XML and + * derives the spring implementation componentType from it + */ + public void resolve(SpringImplementation springImplementation, ModelResolver resolver, ProcessorContext context) + throws ContributionResolveException { + + if (springImplementation == null) + return; + + Monitor monitor = context.getMonitor(); + /* Load the Spring component type by reading the Spring application context */ + SpringXMLComponentTypeLoader springLoader = new SpringXMLComponentTypeLoader(registry); + try { + // Load the Spring Implementation information from its application context file... + springLoader.load(springImplementation, resolver, context); + } catch (ContributionReadException e) { + ContributionResolveException ce = new ContributionResolveException(e); + error(monitor, "ContributionResolveException", resolver, ce); + throw ce; + } + + ComponentType ct = springImplementation.getComponentType(); + if (ct.isUnresolved()) { + // If the introspection fails to resolve, try to find a side file... + ComponentType componentType = resolver.resolveModel(ComponentType.class, ct, context); + if (componentType.isUnresolved()) { + error(monitor, "UnableToResolveComponentType", resolver); + //throw new ContributionResolveException("SpringArtifactProcessor: unable to resolve componentType for Spring component"); + } else { + springImplementation.setComponentType(componentType); + springImplementation.setUnresolved(false); + } + + } // end if + + } // end method resolve + + public QName getArtifactType() { + return IMPLEMENTATION_SPRING_QNAME; + } + + public Class<SpringImplementation> getModelType() { + return SpringImplementation.class; + } + +} // end class SpringArtifactProcessor diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringXMLBeanDefinitionLoader.java b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringXMLBeanDefinitionLoader.java new file mode 100644 index 0000000000..a3dc353ffc --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringXMLBeanDefinitionLoader.java @@ -0,0 +1,50 @@ +/* + * 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.tuscany.sca.implementation.spring.xml; + +import java.net.URL; +import java.util.List; + +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.implementation.spring.SpringBeanElement; +import org.apache.tuscany.sca.implementation.spring.SpringSCAPropertyElement; +import org.apache.tuscany.sca.implementation.spring.SpringSCAReferenceElement; +import org.apache.tuscany.sca.implementation.spring.SpringSCAServiceElement; + +/** + * The utility interface to load Spring XML bean definitions into an application context + */ +public interface SpringXMLBeanDefinitionLoader { + /** + * @param resources + * @param serviceElements + * @param referenceElements + * @param propertyElements + * @param beanElements + * @param context + * @return + */ + Object load(List<URL> resources, + List<SpringSCAServiceElement> serviceElements, + List<SpringSCAReferenceElement> referenceElements, + List<SpringSCAPropertyElement> propertyElements, + List<SpringBeanElement> beanElements, + ProcessorContext context); +} diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.assembly.builder.ImplementationBuilder b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.assembly.builder.ImplementationBuilder new file mode 100644 index 0000000000..7ea615051e --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.assembly.builder.ImplementationBuilder @@ -0,0 +1,18 @@ +# 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.
+org.apache.tuscany.sca.implementation.spring.SpringImplementationBuilder;qname=http://docs.oasis-open.org/ns/opencsa/sca/200912#implementation.spring
+
diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor new file mode 100644 index 0000000000..880d6fade0 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor @@ -0,0 +1,20 @@ +# 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.
+
+# Implementation class for the artifact processor extension
+org.apache.tuscany.sca.implementation.spring.xml.SpringImplementationProcessor;qname=http://docs.oasis-open.org/ns/opencsa/sca/200912#implementation.spring,model=org.apache.tuscany.sca.implementation.spring.SpringImplementation
+
diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.definitions.xml.Definitions b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.definitions.xml.Definitions new file mode 100644 index 0000000000..4a9270d094 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.definitions.xml.Definitions @@ -0,0 +1,17 @@ +# 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.
+org/apache/tuscany/sca/implementation/spring/definitions.xml
diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/resources/impl-spring-validation-messages.properties b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/resources/impl-spring-validation-messages.properties new file mode 100644 index 0000000000..28bd31ca11 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/resources/impl-spring-validation-messages.properties @@ -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. +# +# +LocationAttributeMissing = Reading implementation.spring - location attribute missing +ContributionResolveException = ContributionResolveException occured due to: +UnableToResolveComponentType = SpringArtifactProcessor: unable to resolve componentType for Spring component +ScaServiceNameNotUnique = The value of the @name attribute of an <sca:service/> element MUST be unique amongst the <sca:service/> subelements of the <beans/> element +ScaReferenceNameNotUnique = The value of the @name attribute of an <sca:reference/> element MUST be unique amongst the <sca:reference/> subelements of the <beans/> element +ScaPropertyNameNotUnique = The value of the @name attribute of an <sca:property/> element MUST be unique amongst the <sca:property/> subelements of the <beans/> element +DefaultBeanDoesNotExist = The @default attribute of a <sca:reference/> element MUST have the value of the @name attribute of one of the <bean/> subelements of the <beans/> element. +TargetBeanDoesNotExist = The @target attribute of a <sca:service/> element MUST have the value of the @name attribute of one of the <bean/> subelements of the <beans/> element. diff --git a/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/resources/org/apache/tuscany/sca/implementation/spring/definitions.xml b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/resources/org/apache/tuscany/sca/implementation/spring/definitions.xml new file mode 100644 index 0000000000..18e7b1e60a --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/implementation-spring/src/main/resources/org/apache/tuscany/sca/implementation/spring/definitions.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> + +<!-- $Rev$ $Date$ --> + +<sca:definitions xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" + targetNamespace="http://docs.oasis-open.org/ns/opencsa/sca/200912" + xmlns:sca="http://docs.oasis-open.org/ns/opencsa/sca/200912" + xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.1"> + + <sca:implementationType type="sca:implementation.spring" mayProvide="" alwaysProvides=""/> + + </sca:definitions> diff --git a/sandbox/sebastien/java/extend/contrib/modules/pom.xml b/sandbox/sebastien/java/extend/contrib/modules/pom.xml new file mode 100644 index 0000000000..238ee4dd06 --- /dev/null +++ b/sandbox/sebastien/java/extend/contrib/modules/pom.xml @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<project> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-sca</artifactId> + <version>2.0-SNAPSHOT</version> + <relativePath>../../pom.xml</relativePath> + </parent> + <artifactId>tuscany-contrib-modules</artifactId> + <packaging>pom</packaging> + <name>Apache Tuscany SCA Contributed Modules</name> + + <modules> + <module>databinding-protobuf</module> + <module>host-tomcat</module> + </modules> + + <profiles> + <profile> + <id>eclipse</id> + <build> + <defaultGoal>org.apache.tuscany.maven.plugins:maven-bundle-plugin:eclipse</defaultGoal> + <!-- + <plugins> + <plugin> + <groupId>org.apache.tuscany.maven.plugins</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <version>1.0.6</version> + <extensions>true</extensions> + <executions> + <execution> + <id>generate-pde</id> + <phase>generate-resources</phase> + <goals> + <goal>eclipse</goal> + </goals> + <configuration> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + --> + </build> + </profile> + </profiles> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.8.1</version> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <pluginManagement> + <plugins> + <plugin> + <artifactId>maven-jar-plugin</artifactId> + <configuration> + <archive> + <manifestFile>${basedir}/META-INF/MANIFEST.MF</manifestFile> + </archive> + </configuration> + </plugin> + </plugins> + </pluginManagement> + </build> + +</project> |