View Javadoc

1   /*
2    * Copyright 2012-2013 smartics, Kronseder & Reiner GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package de.smartics.properties.impl.config.jndi;
17  
18  import java.io.IOException;
19  import java.io.ObjectInputStream;
20  
21  import javax.annotation.concurrent.ThreadSafe;
22  import javax.naming.Context;
23  import javax.naming.InitialContext;
24  import javax.naming.NamingException;
25  
26  import de.smartics.properties.api.config.domain.Property;
27  import de.smartics.properties.api.config.domain.PropertyProvider;
28  import de.smartics.properties.api.config.domain.PropertyStoreAccessor;
29  import de.smartics.properties.api.config.domain.SerializableConfigurationPropertiesManagement;
30  import de.smartics.properties.api.config.domain.key.ConfigurationKey;
31  import de.smartics.properties.api.core.app.JndiContext;
32  import de.smartics.properties.api.core.domain.PropertyDescriptorRegistry;
33  import de.smartics.properties.api.core.security.PropertyValueSecurity;
34  import de.smartics.properties.spi.config.support.AbstractExternalConfigurationPropertiesManagement;
35  import de.smartics.properties.spi.config.support.SerializableConfigurationPropertiesManagementSpi;
36  import de.smartics.util.lang.NullArgumentException;
37  
38  /**
39   * Implementation based on JNDI.
40   */
41  @ThreadSafe
42  public final class JndiConfigurationProperties extends
43      AbstractExternalConfigurationPropertiesManagement implements
44      SerializableConfigurationPropertiesManagement,
45      SerializableConfigurationPropertiesManagementSpi
46  { // NOPMD
47    // ********************************* Fields *********************************
48  
49    // --- constants ------------------------------------------------------------
50  
51    /**
52     * The class version identifier.
53     */
54    private static final long serialVersionUID = 1L;
55  
56    // --- members --------------------------------------------------------------
57  
58    /**
59     * The reference to the configuration within the JNDI context.
60     */
61    private transient JndiContext context;
62  
63    /**
64     * The helper to access properties in a property store directly.
65     *
66     * @serial
67     */
68    private transient PropertyStoreAccessor propertyStoreAccessor;
69  
70    // ****************************** Initializer *******************************
71  
72    // ****************************** Constructors ******************************
73  
74    /**
75     * Default constructor.
76     *
77     * @param key the key that identifies the configuration.
78     * @param registry the registry to resolve property descriptors.
79     * @param decrypter the helper to decrypt secured property values.
80     * @throws NullArgumentException if {@code key}, {@code registry} or
81     *           {@code decrypter} is <code>null</code>.
82     * @throws NamingException if the JNDI context cannot be created.
83     * @throws IllegalArgumentException on any problem accessing the JNDI context.
84     */
85    public JndiConfigurationProperties(final ConfigurationKey<?> key,
86        final PropertyDescriptorRegistry registry,
87        final PropertyValueSecurity decrypter) throws NullArgumentException,
88      NamingException, IllegalArgumentException
89    {
90      super(key, registry, decrypter);
91  
92      this.context = initContext(key);
93      this.propertyStoreAccessor = new JndiPropertyStoreAccessor(key, context);
94    }
95  
96    // ****************************** Inner Classes *****************************
97  
98    // ********************************* Methods ********************************
99  
100   // --- init -----------------------------------------------------------------
101 
102   private static JndiContext initContext(final ConfigurationKey<?> key)
103     throws NamingException, IllegalArgumentException
104   {
105     final Context jndi = new InitialContext();
106     final JndiContext context = JndiContext.config(jndi, key.toString());
107     return context;
108   }
109 
110   // --- get&set --------------------------------------------------------------
111 
112   @Override
113   public PropertyStoreAccessor getPropertyStoreAccessor()
114   {
115     return propertyStoreAccessor;
116   }
117 
118   // --- business -------------------------------------------------------------
119 
120   @Override
121   protected void setPropertiesToStore(final PropertyProvider provider)
122     throws JndiPropertyStoreException
123   {
124     String name = "<unknown>";
125     try
126     {
127       for (final Property property : provider.getProperties())
128       {
129         name = property.getName();
130         final String value = property.getValue();
131         context.set(name, value);
132       }
133     }
134     catch (final NamingException e)
135     {
136       throw new JndiPropertyStoreException(new JndiPropertyStoreMessageBean(
137           JndiPropertyStoreCode.CANNOT_SET_PROPERTY, e, getKey(), name));
138     }
139   }
140 
141 //  /**
142 //   * {@inheritDoc}
143 //   *
144 //   * @impl since JNDI values are currently not persisted.
145 //   * @todo check JNDI configuration for persistence.
146 //   */
147 //  @Override
148 //  protected void addDefinitionsToStore(final PropertyProvider properties)
149 //    throws JndiPropertyStoreException
150 //  {
151 //    setPropertiesToStore(properties);
152 //  }
153 
154   @Override
155   public SerializableConfigurationPropertiesManagement toSerializable()
156   {
157     return this;
158   }
159 
160   // --- object basics --------------------------------------------------------
161 
162   /**
163    * Reads the object from the given stream.
164    *
165    * @param in the stream to read from.
166    * @throws IOException on read problems or if the JNDI context cannot be
167    *           established.
168    * @throws ClassNotFoundException if a class cannot be found.
169    */
170   private void readObject(final ObjectInputStream in) throws IOException,
171     ClassNotFoundException
172   {
173     in.defaultReadObject();
174 
175     try
176     {
177       this.context = initContext(getKey());
178       this.propertyStoreAccessor =
179           new JndiPropertyStoreAccessor(getKey(), context);
180     }
181     catch (final NamingException e)
182     {
183       throw new IOException("Cannot reestablish the JNDI context.", e);
184     }
185     catch (final IllegalArgumentException e)
186     {
187       throw new IOException("Cannot reestablish the JNDI context.", e);
188     }
189   }
190 }