View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.transaction.file;
18  
19  import java.io.ByteArrayInputStream;
20  import java.io.InputStream;
21  import java.io.OutputStream;
22  
23  import org.apache.commons.transaction.util.LoggerFacade;
24  
25  /**
26   * A resource manager for streamable objects stored in a file system that
27   * features additional administration commands.
28   * 
29   * @version $Id: FileResourceManager.java 519647 2007-03-18 17:50:02Z
30   *          ozeigermann $
31   */
32  public class VirtualAdminCommandsFileResourceManager extends
33          FileResourceManager implements ResourceManager,
34          ResourceManagerErrorCodes {
35  
36      protected String virtualAdminPath = null;
37  
38      public String getVirtualAdminPath() {
39          return virtualAdminPath;
40      }
41  
42      public void setVirtualAdminPath(String virutalAdminPath) {
43          this.virtualAdminPath = virutalAdminPath;
44      }
45  
46      /**
47       * Creates a new resource manager operation on the specified directories.
48       * 
49       * @param storeDir
50       *            directory where main data should go after commit
51       * @param workDir
52       *            directory where transactions store temporary data
53       * @param urlEncodePath
54       *            if set to <code>true</code> encodes all paths to allow for
55       *            any kind of characters
56       * @param logger
57       *            the logger to be used by this store
58       */
59      public VirtualAdminCommandsFileResourceManager(String storeDir,
60              String workDir, boolean urlEncodePath, LoggerFacade logger) {
61          this(storeDir, workDir, urlEncodePath, logger, false);
62      }
63  
64      /**
65       * Creates a new resource manager operation on the specified directories.
66       * 
67       * @param storeDir
68       *            directory where main data should go after commit
69       * @param workDir
70       *            directory where transactions store temporary data
71       * @param urlEncodePath
72       *            if set to <code>true</code> encodes all paths to allow for
73       *            any kind of characters
74       * @param logger
75       *            the logger to be used by this store
76       * @param debug
77       *            if set to <code>true</code> logs all locking information to
78       *            "transaction.log" for debugging inspection
79       */
80      public VirtualAdminCommandsFileResourceManager(String storeDir,
81              String workDir, boolean urlEncodePath, LoggerFacade logger,
82              boolean debug) {
83          this(storeDir, workDir, urlEncodePath ? new URLEncodeIdMapper() : null,
84                  new NoOpTransactionIdToPathMapper(), logger, debug);
85      }
86  
87      /**
88       * Creates a new resource manager operation on the specified directories.
89       * This constructor is reintroduced for backwards API compatibility and is
90       * used by jakarta-slide.
91       * 
92       * @param storeDir
93       *            directory where main data should go after commit
94       * @param workDir
95       *            directory where transactions store temporary data
96       * @param idMapper
97       *            mapper for resourceId to path
98       * @param logger
99       *            the logger to be used by this store
100      * @param debug
101      *            if set to <code>true</code> logs all locking information to
102      *            "transaction.log" for debugging inspection
103      */
104     public VirtualAdminCommandsFileResourceManager(String storeDir,
105             String workDir, ResourceIdToPathMapper idMapper,
106             LoggerFacade logger, boolean debug) {
107         this(storeDir, workDir, idMapper, new NoOpTransactionIdToPathMapper(),
108                 logger, debug);
109     }
110 
111     /**
112      * Creates a new resource manager operation on the specified directories.
113      * 
114      * @param storeDir
115      *            directory where main data should go after commit
116      * @param workDir
117      *            directory where transactions store temporary data
118      * @param idMapper
119      *            mapper for resourceId to path
120      * @param txIdMapper
121      *            mapper for transaction id to path
122      * @param logger
123      *            the logger to be used by this store
124      * @param debug
125      *            if set to <code>true</code> logs all locking information to
126      *            "transaction.log" for debugging inspection
127      */
128     public VirtualAdminCommandsFileResourceManager(String storeDir,
129             String workDir, ResourceIdToPathMapper idMapper,
130             TransactionIdToPathMapper txIdMapper, LoggerFacade logger,
131             boolean debug) {
132         super(workDir, storeDir, idMapper, txIdMapper, logger, debug);
133     }
134 
135     public boolean resourceExists(Object resourceId)
136             throws ResourceManagerException {
137         if (isVirtualAdminId(resourceId)) {
138             logger
139                     .logFine("Faking existence of virtual administration command");
140             return true;
141         }
142 
143         return super.resourceExists(resourceId);
144     }
145 
146     public boolean resourceExists(Object txId, Object resourceId)
147             throws ResourceManagerException {
148         if (isVirtualAdminId(resourceId)) {
149             logger
150                     .logFine("Faking existence of virtual administration command");
151             return true;
152         }
153 
154         return super.resourceExists(txId, resourceId);
155     }
156 
157     public void deleteResource(Object txId, Object resourceId)
158             throws ResourceManagerException {
159 
160         checkForVirtualAdminCommand(resourceId);
161 
162         super.deleteResource(txId, resourceId);
163     }
164 
165     public void deleteResource(Object txId, Object resourceId,
166             boolean assureOnly) throws ResourceManagerException {
167 
168         checkForVirtualAdminCommand(resourceId);
169 
170         super.deleteResource(txId, resourceId, assureOnly);
171     }
172 
173     public void createResource(Object txId, Object resourceId)
174             throws ResourceManagerException {
175 
176         checkForVirtualAdminCommand(resourceId);
177 
178         super.createResource(txId, resourceId);
179     }
180 
181     public void createResource(Object txId, Object resourceId,
182             boolean assureOnly) throws ResourceManagerException {
183 
184         checkForVirtualAdminCommand(resourceId);
185 
186         super.createResource(txId, resourceId, assureOnly);
187     }
188 
189     public void copyResource(Object txId, Object fromResourceId,
190             Object toResourceId, boolean overwrite)
191             throws ResourceManagerException {
192 
193         checkForVirtualAdminCommand(fromResourceId);
194         checkForVirtualAdminCommand(toResourceId);
195 
196         super.copyResource(txId, fromResourceId, toResourceId, overwrite);
197     }
198 
199     public void moveResource(Object txId, Object fromResourceId,
200             Object toResourceId, boolean overwrite)
201             throws ResourceManagerException {
202 
203         checkForVirtualAdminCommand(fromResourceId);
204         checkForVirtualAdminCommand(toResourceId);
205 
206         super.moveResource(txId, fromResourceId, toResourceId, overwrite);
207     }
208 
209     public InputStream readResource(Object resourceId)
210             throws ResourceManagerException {
211 
212         if (isVirtualAdminId(resourceId)) {
213             logger.logWarning("Issuing virtual admin command" + resourceId);
214             return executeAdminCommand(resourceId);
215         }
216 
217         return super.readResource(resourceId);
218     }
219 
220     public InputStream readResource(Object txId, Object resourceId)
221             throws ResourceManagerException {
222 
223         if (isVirtualAdminId(resourceId)) {
224             String message = "You must not call virtual admin commands ("
225                     + resourceId + ") from within transactions!";
226             logger.logSevere(message);
227             throw new ResourceManagerException(message);
228         }
229 
230         return super.readResource(txId, resourceId);
231     }
232 
233     protected void checkForVirtualAdminCommand(Object resourceId)
234             throws ResourceManagerException {
235         if (isVirtualAdminId(resourceId)) {
236             String message = "You must not make modification calls to virtual admin commands ("
237                     + resourceId + ")!";
238             logger.logSevere(message);
239             throw new ResourceManagerException(message);
240         }
241     }
242 
243     protected boolean isVirtualAdminId(Object resourceId) {
244         return (getVirtualAdminPath() != null && resourceId.toString()
245                 .startsWith(getVirtualAdminPath()));
246     }
247 
248     protected InputStream executeAdminCommand(Object resourceId) {
249         StringBuffer sb = new StringBuffer();
250 
251         if (!isVirtualAdminId(resourceId)) {
252             String message = "Internal error: " + resourceId.toString()
253                     + " is no administration command, but is supposed to!";
254             sb.append(message);
255             logger.logSevere(message);
256         } else {
257             String command = resourceId.toString().substring(
258                     getVirtualAdminPath().length());
259             logger.logInfo("Processing admin command " + command);
260 
261             // XXX this really should be more flexible
262             try {
263                 if (isAKnowCommand(command)) {
264                     if (command.equals("recover")) {
265                         recover();
266                     }
267 
268                     String message = "Command " + command
269                             + " terminated successfully";
270                     sb.append(message);
271                     logger.logInfo(message);
272                 } else {
273                     String message = "Command " + command + " unknown";
274                     sb.append(message);
275                     logger.logWarning(message);
276 
277                 }
278             } catch (ResourceManagerSystemException e) {
279                 String message = "Command " + command
280                         + " failed with the following message: "
281                         + e.getMessage();
282                 sb.append(message);
283                 logger.logSevere(message, e);
284             }
285 
286         }
287         ByteArrayInputStream baIs = new ByteArrayInputStream(sb.toString()
288                 .getBytes());
289         return baIs;
290 
291     }
292 
293     protected boolean isAKnowCommand(String command) {
294         return command.equals("recover");
295     }
296 
297     public OutputStream writeResource(Object txId, Object resourceId,
298             boolean append) throws ResourceManagerException {
299 
300         checkForVirtualAdminCommand(resourceId);
301 
302         return super.writeResource(txId, resourceId, append);
303     }
304 }