1 16 package org.apache.cocoon.components.repository; 17 18 import java.io.IOException ; 19 import java.util.Iterator ; 20 21 import org.apache.avalon.framework.logger.AbstractLogEnabled; 22 import org.apache.avalon.framework.service.ServiceException; 23 import org.apache.avalon.framework.service.ServiceManager; 24 import org.apache.avalon.framework.service.Serviceable; 25 import org.apache.avalon.framework.thread.ThreadSafe; 26 import org.apache.excalibur.source.ModifiableSource; 27 import org.apache.excalibur.source.ModifiableTraversableSource; 28 import org.apache.excalibur.source.Source; 29 import org.apache.excalibur.source.SourceException; 30 import org.apache.excalibur.source.SourceResolver; 31 import org.apache.excalibur.source.SourceUtil; 32 import org.apache.excalibur.source.TraversableSource; 33 34 39 public class SourceRepositoryImpl extends AbstractLogEnabled 40 implements Serviceable, ThreadSafe, SourceRepository { 41 42 private RepositoryInterceptor m_interceptor = new RepositoryInterceptorBase(){}; 43 private SourceResolver m_resolver; 44 45 46 48 public SourceRepositoryImpl() { 49 } 50 51 public void service(ServiceManager manager) throws ServiceException { 52 m_resolver = (SourceResolver) manager.lookup(SourceResolver.ROLE); 53 if (manager.hasService(RepositoryInterceptor.ROLE)) { 54 m_interceptor = (RepositoryInterceptor) manager.lookup(RepositoryInterceptor.ROLE); 55 } 56 } 57 58 59 61 public int save(String in, String out) throws IOException , SourceException { 62 63 if (getLogger().isDebugEnabled()) { 64 getLogger().debug("save: "+in+"/"+out); 65 } 66 67 Source source = null; 68 Source destination = null; 69 try { 70 destination = m_resolver.resolveURI(out); 71 72 if (!(destination instanceof ModifiableSource)) { 73 final String message = 74 "Conflict during save(): protocol is not modifiable."; 75 getLogger().warn(message); 76 return STATUS_CONFLICT; 77 } 78 79 final boolean exists = destination.exists(); 80 if (!exists) { 81 Source parent = ((TraversableSource) destination).getParent(); 82 if (!parent.exists()) { 83 final String message = 84 "Conflict during save(): parent does not exist."; 85 getLogger().warn(message); 86 return STATUS_CONFLICT; 87 } 88 } 89 90 if (destination instanceof TraversableSource) { 91 if (((TraversableSource) destination).isCollection()) { 92 final String message = 93 "Conflict during save(): destination is a collection."; 94 getLogger().warn(message); 95 return STATUS_CONFLICT; 96 } 97 } 98 99 int status; 100 if (exists) { 101 status = STATUS_OK; 102 } 103 else { 104 status = STATUS_CREATED; 105 } 106 107 source = m_resolver.resolveURI(in); 108 m_interceptor.preStoreSource(destination); 109 SourceUtil.copy(source,destination); 110 m_interceptor.postStoreSource(destination); 111 return status; 112 } 113 catch (IOException e) { 114 getLogger().error("Unexpected exception during save().",e); 115 throw e; 116 } 117 finally { 118 if (source != null) { 119 m_resolver.release(source); 120 } 121 if (destination != null) { 122 m_resolver.release(destination); 123 } 124 } 125 126 } 127 128 public int makeCollection(String location) throws IOException , SourceException { 129 130 if (getLogger().isDebugEnabled()) { 131 getLogger().debug("makeCollection: " + location); 132 } 133 134 Source source = null; 135 Source parent = null; 136 try { 137 source = m_resolver.resolveURI(location); 138 139 if (source.exists()) { 140 final String message = 141 "makeCollection() is not allowed: the resource already exists."; 142 getLogger().warn(message); 143 return STATUS_NOT_ALLOWED; 144 } 145 146 if (!(source instanceof ModifiableTraversableSource)) { 147 final String message = 148 "Conflict in makeCollection(): source is not modifiable traversable."; 149 getLogger().warn(message); 150 return STATUS_CONFLICT; 151 } 152 153 parent = ((TraversableSource) source).getParent(); 154 if (!parent.exists()) { 155 final String message = "Conflict in makeCollection(): parent does not exist."; 156 getLogger().warn(message); 157 return STATUS_CONFLICT; 158 } 159 160 m_interceptor.preStoreSource(source); 161 ((ModifiableTraversableSource) source).makeCollection(); 162 m_interceptor.postStoreSource(source); 163 return STATUS_CREATED; 164 } 165 catch (IOException e) { 166 getLogger().error("Unexpected exception during makeCollection().",e); 167 throw e; 168 } 169 finally { 170 if (source != null) { 171 m_resolver.release(source); 172 } 173 if (parent != null) { 174 m_resolver.release(parent); 175 } 176 } 177 } 178 179 186 public int remove(String location) throws IOException , SourceException { 187 188 Source source = null; 189 try { 190 source = m_resolver.resolveURI(location); 191 if (!source.exists()) { 192 final String message = 193 "Trying to remove a non-existing source."; 194 getLogger().warn(message); 195 return STATUS_NOT_FOUND; 196 } 197 return remove(source); 198 } 199 catch (IOException e) { 200 getLogger().error("Unexpected exception during remove().",e); 201 throw e; 202 } 203 finally { 204 if (source != null) { 205 m_resolver.release(source); 206 } 207 } 208 209 } 210 211 private int remove(Source source) throws SourceException { 212 213 if (getLogger().isDebugEnabled()) { 214 getLogger().debug("remove: " + source.getURI()); 215 } 216 217 if (!(source instanceof ModifiableSource)) { 218 final String message = 219 "Conflict in remove(): source is not modifiable"; 220 getLogger().warn(message); 221 return STATUS_CONFLICT; 222 } 223 224 if (source instanceof TraversableSource) { 225 if (((TraversableSource) source).isCollection()) { 226 int status = STATUS_OK; 227 final Iterator iter = ((TraversableSource) source).getChildren().iterator(); 228 while (iter.hasNext()) { 229 status = remove((Source) iter.next()); 230 if (status != STATUS_OK) { 231 return status; 232 } 233 } 234 } 235 } 236 m_interceptor.preRemoveSource(source); 237 ((ModifiableSource) source).delete(); 238 m_interceptor.postRemoveSource(source); 239 return STATUS_OK; 240 } 241 242 public int move(String from, String to, boolean recurse, boolean overwrite) 243 throws IOException , SourceException { 244 245 int status = doCopy(from,to,recurse,overwrite); 246 if (status == STATUS_CREATED || status == STATUS_NO_CONTENT) { 247 remove(from); 249 } 251 return status; 252 } 253 254 public int copy(String from, String to, boolean recurse, boolean overwrite) 255 throws IOException , SourceException { 256 257 return doCopy(from,to,recurse,overwrite); 258 259 } 260 261 private int doCopy(String from, String to, boolean recurse, boolean overwrite) 262 throws IOException { 263 264 if (getLogger().isDebugEnabled()) { 265 getLogger().debug("copy: " + from + " -> " + to 266 + " (recurse=" + recurse + ", overwrite=" + overwrite + ")"); 267 } 268 269 if (from != null && from.equals(to)) { 270 final String message = 271 "copy() is forbidden: " + 272 "The source and destination URIs are the same."; 273 getLogger().warn(message); 274 return STATUS_FORBIDDEN; 275 } 276 Source source = null; 277 Source destination = null; 278 try { 279 source = m_resolver.resolveURI(from); 280 destination = m_resolver.resolveURI(to); 281 if (!source.exists()) { 282 final String message = 283 "Trying to copy a non-existing source."; 284 getLogger().warn(message); 285 return STATUS_NOT_FOUND; 286 } 287 int status; 288 if (destination.exists()) { 289 if (!overwrite) { 290 final String message = 291 "Failed precondition in copy(): " + 292 "Destination resource already exists."; 293 getLogger().warn(message); 294 return STATUS_PRECONDITION_FAILED; 295 } 296 remove(destination); 297 status = STATUS_NO_CONTENT; 298 } 299 else { 300 Source parent = null; 301 try { 302 parent = getParent(destination); 303 if (!parent.exists()) { 304 final String message = 305 "Conflict in copy(): " + 306 "A resource cannot be created at the destination " + 307 "until one or more intermediate collections have been " + 308 "created."; 309 getLogger().warn(message); 310 return STATUS_CONFLICT; 311 } 312 } 313 finally { 314 if (parent != null) { 315 m_resolver.release(parent); 316 } 317 } 318 status = STATUS_CREATED; 319 } 320 copy(source,destination,recurse); 321 return status; 322 } 323 catch (IOException e) { 324 getLogger().error("Unexpected exception during copy().",e); 325 throw e; 326 } 327 finally { 328 if (source != null) { 329 m_resolver.release(source); 330 } 331 if (destination != null) { 332 m_resolver.release(destination); 333 } 334 } 335 } 336 337 private int copy(Source source, Source destination, boolean recurse) 338 throws IOException { 339 340 if (getLogger().isDebugEnabled()) { 341 getLogger().debug("copy: " + source.getURI() + " -> " + destination.getURI()); 342 } 343 344 if (source instanceof TraversableSource) { 345 final TraversableSource origin = (TraversableSource) source; 346 ModifiableTraversableSource target = null; 347 if (origin.isCollection()) { 348 if (!(destination instanceof ModifiableTraversableSource)) { 349 final String message = "copy() is forbidden: " + 350 "Cannot create a collection at the indicated destination."; 351 getLogger().warn(message); 352 return STATUS_FORBIDDEN; 353 } 354 target = ((ModifiableTraversableSource) destination); 356 m_interceptor.preStoreSource(target); 357 target.makeCollection(); 358 m_interceptor.postStoreSource(target); 359 if (recurse) { 360 Iterator children = origin.getChildren().iterator(); 361 while (children.hasNext()) { 362 TraversableSource child = (TraversableSource) children.next(); 363 copy(child,target.getChild(child.getName()),recurse); 364 } 368 } 369 return STATUS_CREATED; 370 } 371 } 372 if (destination instanceof ModifiableSource) { 373 m_interceptor.preStoreSource(destination); 375 SourceUtil.copy(source,destination); 376 m_interceptor.postStoreSource(destination); 377 } 378 else { 379 final String message = "copy() is forbidden: " + 380 "Cannot create a resource at the indicated destination."; 381 getLogger().warn(message); 382 return STATUS_FORBIDDEN; 383 } 384 return STATUS_CREATED; 385 } 386 387 private Source getParent(Source source) throws IOException { 388 if (source instanceof TraversableSource) { 389 return ((TraversableSource) source).getParent(); 390 } 391 else { 392 String uri = source.getURI(); 393 int index = uri.lastIndexOf('/'); 394 if (index != -1) { 395 return m_resolver.resolveURI(uri.substring(index+1)); 396 } 397 } 398 return null; 399 } 400 401 } 402 | Popular Tags |