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.vfs2.operations;
18  
19  import java.util.ArrayList;
20  import java.util.Collection;
21  
22  import org.apache.commons.vfs2.FileObject;
23  import org.apache.commons.vfs2.FileSystemException;
24  
25  /**
26   * Abstracts implementations of {@link FileOperationProvider}.
27   *
28   * @since 0.1
29   */
30  public abstract class AbstractFileOperationProvider implements FileOperationProvider {
31  
32      /**
33       * Available operations. Operations could be registered for different schemes. Some operations can work only for
34       * "file" scheme, other - for "svnhttp(s)", "svn", "svnssh", but not for "file", etc. The Map has scheme as a key
35       * and Collection of operations that are available for that scheme.
36       */
37      private final Collection<Class<? extends FileOperation>> operations = new ArrayList<>();
38  
39      /**
40       * Constructs a new instance for subclasses.
41       */
42      public AbstractFileOperationProvider() {
43          // empty
44      }
45  
46      /**
47       * Add new FileOperation to list of known operations.
48       *
49       * @param operationClass a class implementing FileOperation.
50       * @throws FileSystemException if instances of the class cannot be assigned to FileOperation.
51       */
52      protected final void addOperation(final Class<? extends FileOperation> operationClass) throws FileSystemException {
53          // check validity of passed class
54          if (!FileOperation.class.isAssignableFrom(operationClass)) {
55              throw new FileSystemException("vfs.operation/cant-register.error", operationClass);
56          }
57  
58          // ok, lets add it to the list
59          operations.add(operationClass);
60      }
61  
62      /**
63       * Gather available operations for the specified FileObject and put them into specified operationsList.
64       *
65       * @param operationsList the list of available operations for the specified FileObject. The operationList contains
66       *            classes of available operations, e.g. Class objects.
67       * @param file the FileObject for which we want to get the list of available operations.
68       * @throws FileSystemException if list of operations cannot be retrieved.
69       */
70      @Override
71      public final void collectOperations(final Collection<Class<? extends FileOperation>> operationsList,
72              final FileObject file) throws FileSystemException {
73          doCollectOperations(operations, operationsList, file);
74      }
75  
76      /**
77       * Gather available operations for the specified FileObject and put them into specified operationsList.
78       *
79       * @param availableOperations the list of available operations for the specified FileObject.
80       * @param resultList List to be filled with applicable operations.
81       * @param file the FileObject for which we want to get the list of available operations.
82       * @throws FileSystemException if list of operations cannot be retrieved.
83       * @see #collectOperations(Collection operationsList, FileObject file)
84       */
85      protected abstract void doCollectOperations(Collection<Class<? extends FileOperation>> availableOperations,
86          Collection<Class<? extends FileOperation>> resultList, FileObject file) throws FileSystemException;
87  
88      /**
89       * @param file the FileObject for which we need an operation.
90       * @param operationClass the Class which instance we are needed.
91       * @return the required operation instance.
92       * @throws FileSystemException if operation cannot be retrieved.
93       */
94      @Override
95      public final FileOperation getOperation(final FileObject file, final Class<? extends FileOperation> operationClass)
96              throws FileSystemException {
97          return instantiateOperation(file, lookupOperation(operationClass));
98      }
99  
100     /**
101      * Gets operation instance for specified FileOperation subclass.
102      *
103      * @param file the file this operation should act on.
104      * @param operationClass the class of a file operation interface to instantiate.
105      * @return a new file operation
106      * @throws FileSystemException if operation cannot be instantiated.
107      */
108     protected abstract FileOperation instantiateOperation(FileObject file, Class<? extends FileOperation> operationClass) throws FileSystemException;
109 
110     /**
111      * Find class implementing a specific operation interface.
112      *
113      * @param operationClass the interface which is requested.
114      * @return never returns null
115      * @throws FileSystemException if operationClass is not a known FileOperation interface.
116      */
117     protected final Class<? extends FileOperation> lookupOperation(final Class<? extends FileOperation> operationClass)
118             throws FileSystemException {
119         // check validity of passed class
120         if (!FileOperation.class.isAssignableFrom(operationClass)) {
121             throw new FileSystemException("vfs.operation/wrong-type.error", operationClass);
122         }
123 
124         // find appropriate class
125         Class<? extends FileOperation> foundClass = null;
126         for (final Class<? extends FileOperation> operation : operations) {
127             if (operationClass.isAssignableFrom(operation)) {
128                 foundClass = operation;
129                 break;
130             }
131         }
132 
133         if (foundClass == null) {
134             throw new FileSystemException("vfs.operation/not-found.error", operationClass);
135         }
136 
137         return foundClass;
138     }
139 }