001 /* 002 Licensed to the Apache Software Foundation (ASF) under one 003 or more contributor license agreements. See the NOTICE file 004 distributed with this work for additional information 005 regarding copyright ownership. The ASF licenses this file 006 to you under the Apache License, Version 2.0 (the 007 "License"); you may not use this file except in compliance 008 with the License. You may obtain a copy of the License at 009 010 http://www.apache.org/licenses/LICENSE-2.0 011 012 Unless required by applicable law or agreed to in writing, 013 software distributed under the License is distributed on an 014 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 KIND, either express or implied. See the License for the 016 specific language governing permissions and limitations 017 under the License. 018 */ 019 package org.apache.wiki; 020 021 import java.util.Date; 022 import java.util.Enumeration; 023 import java.util.HashMap; 024 import java.util.Map; 025 026 import org.apache.wiki.auth.acl.Acl; 027 import org.apache.wiki.auth.acl.AclEntry; 028 import org.apache.wiki.auth.acl.AclImpl; 029 import org.apache.wiki.providers.WikiPageProvider; 030 031 /** 032 * Simple wrapper class for the Wiki page attributes. The Wiki page 033 * content is moved around in Strings, though. 034 */ 035 036 // FIXME: We need to rethink how metadata is being used - probably the 037 // author, date, etc. should also be part of the metadata. We also 038 // need to figure out the metadata lifecycle. 039 040 public class WikiPage 041 implements Cloneable, 042 Comparable 043 { 044 private static final long serialVersionUID = 1L; 045 046 private String m_name; 047 private WikiEngine m_engine; 048 private String m_wiki; 049 private Date m_lastModified; 050 private long m_fileSize = -1; 051 private int m_version = WikiPageProvider.LATEST_VERSION; 052 private String m_author = null; 053 private final HashMap<String,Object> m_attributes = new HashMap<String,Object>(); 054 055 /** 056 * "Summary" is a short summary of the page. It is a String. 057 */ 058 public static final String DESCRIPTION = "summary"; 059 060 /** A special variable name for storing a page alias. */ 061 public static final String ALIAS = "alias"; 062 063 /** A special variable name for storing a redirect note */ 064 public static final String REDIRECT = "redirect"; 065 066 /** A special variable name for storing a changenote. */ 067 public static final String CHANGENOTE = "changenote"; 068 069 private Acl m_accessList = null; 070 071 /** 072 * Create a new WikiPage using a given engine and name. 073 * 074 * @param engine The WikiEngine that owns this page. 075 * @param name The name of the page. 076 */ 077 public WikiPage( WikiEngine engine, String name ) 078 { 079 m_engine = engine; 080 m_name = name; 081 m_wiki = engine.getApplicationName(); 082 } 083 084 /** 085 * Returns the name of the page. 086 * 087 * @return The page name. 088 */ 089 public String getName() 090 { 091 return m_name; 092 } 093 094 /** 095 * A WikiPage may have a number of attributes, which might or might not be 096 * available. Typically attributes are things that do not need to be stored 097 * with the wiki page to the page repository, but are generated 098 * on-the-fly. A provider is not required to save them, but they 099 * can do that if they really want. 100 * 101 * @param key The key using which the attribute is fetched 102 * @return The attribute. If the attribute has not been set, returns null. 103 */ 104 public Object getAttribute( String key ) 105 { 106 return m_attributes.get( key ); 107 } 108 109 /** 110 * Sets an metadata attribute. 111 * 112 * @see #getAttribute(String) 113 * @param key The key for the attribute used to fetch the attribute later on. 114 * @param attribute The attribute value 115 */ 116 public void setAttribute( String key, Object attribute ) 117 { 118 m_attributes.put( key, attribute ); 119 } 120 121 /** 122 * Returns the full attributes Map, in case external code needs 123 * to iterate through the attributes. 124 * 125 * @return The attribute Map. Please note that this is a direct 126 * reference, not a copy. 127 */ 128 public Map getAttributes() 129 { 130 return m_attributes; 131 } 132 133 /** 134 * Removes an attribute from the page, if it exists. 135 * 136 * @param key The key for the attribute 137 * @return If the attribute existed, returns the object. 138 * @since 2.1.111 139 */ 140 public Object removeAttribute( String key ) 141 { 142 return m_attributes.remove( key ); 143 } 144 145 /** 146 * Returns the date when this page was last modified. 147 * 148 * @return The last modification date 149 */ 150 public Date getLastModified() 151 { 152 return m_lastModified; 153 } 154 155 /** 156 * Sets the last modification date. In general, this is only 157 * changed by the provider. 158 * 159 * @param date The date 160 */ 161 public void setLastModified( Date date ) 162 { 163 m_lastModified = date; 164 } 165 166 /** 167 * Sets the page version. In general, this is only changed 168 * by the provider. 169 * 170 * @param version The version number 171 */ 172 public void setVersion( int version ) 173 { 174 m_version = version; 175 } 176 177 /** 178 * Returns the version that this WikiPage instance represents. 179 * 180 * @return the version number of this page. 181 */ 182 public int getVersion() 183 { 184 return m_version; 185 } 186 187 /** 188 * Returns the size of the page. 189 * 190 * @return the size of the page. 191 * @since 2.1.109 192 */ 193 public long getSize() 194 { 195 return m_fileSize; 196 } 197 198 /** 199 * Sets the size. Typically called by the provider only. 200 * 201 * @param size The size of the page. 202 * @since 2.1.109 203 */ 204 public void setSize( long size ) 205 { 206 m_fileSize = size; 207 } 208 209 /** 210 * Returns the Acl for this page. May return <code>null</code>, 211 * in case there is no Acl defined, or it has not 212 * yet been set by {@link #setAcl(Acl)}. 213 * 214 * @return The access control list. May return null, if there is 215 * no acl. 216 */ 217 public Acl getAcl() 218 { 219 return m_accessList; 220 } 221 222 /** 223 * Sets the Acl for this page. Note that method does <em>not</em> 224 * persist the Acl itself to back-end storage or in page markup; 225 * it merely sets the internal field that stores the Acl. To 226 * persist the Acl, callers should invoke 227 * {@link org.apache.wiki.auth.acl.AclManager#setPermissions(WikiPage, Acl)}. 228 * @param acl The Acl to set 229 */ 230 public void setAcl( Acl acl ) 231 { 232 m_accessList = acl; 233 } 234 235 /** 236 * Sets the author of the page. Typically called only by the provider. 237 * 238 * @param author The author name. 239 */ 240 public void setAuthor( String author ) 241 { 242 m_author = author; 243 } 244 245 /** 246 * Returns author name, or null, if no author has been defined. 247 * 248 * @return Author name, or possibly null. 249 */ 250 public String getAuthor() 251 { 252 return m_author; 253 } 254 255 /** 256 * Returns the wiki nanme for this page 257 * 258 * @return The name of the wiki. 259 */ 260 public String getWiki() 261 { 262 return m_wiki; 263 } 264 265 /** 266 * This method will remove all metadata from the page. 267 */ 268 public void invalidateMetadata() 269 { 270 m_hasMetadata = false; 271 setAcl( null ); 272 m_attributes.clear(); 273 } 274 275 private boolean m_hasMetadata = false; 276 277 /** 278 * Returns <code>true</code> if the page has valid metadata; that is, it has been parsed. 279 * Note that this method is a kludge to support our pre-3.0 metadata system, and as such 280 * will go away with the new API. 281 * 282 * @return true, if the page has metadata. 283 */ 284 public boolean hasMetadata() 285 { 286 return m_hasMetadata; 287 } 288 289 /** 290 * Sets the metadata flag to true. Never call. 291 */ 292 public void setHasMetadata() 293 { 294 m_hasMetadata = true; 295 } 296 297 /** 298 * Returns a debug-suitable version of the page. 299 * 300 * @return A debug string. 301 */ 302 public String toString() 303 { 304 return "WikiPage ["+m_wiki+":"+m_name+",ver="+m_version+",mod="+m_lastModified+"]"; 305 } 306 307 /** 308 * Creates a deep clone of a WikiPage. Strings are not cloned, since 309 * they're immutable. Attributes are not cloned, only the internal 310 * HashMap (so if you modify the contents of a value of an attribute, 311 * these will reflect back to everyone). 312 * 313 * @return A deep clone of the WikiPage 314 */ 315 public Object clone() 316 { 317 WikiPage p = new WikiPage( m_engine, m_name ); 318 319 p.m_wiki = m_wiki; 320 321 p.m_author = m_author; 322 p.m_version = m_version; 323 p.m_lastModified = m_lastModified != null ? (Date)m_lastModified.clone() : null; 324 325 p.m_fileSize = m_fileSize; 326 327 for( Map.Entry<String,Object> entry : m_attributes.entrySet() ) 328 { 329 p.m_attributes.put( entry.getKey(), 330 entry.getValue() ); 331 } 332 333 if( m_accessList != null ) 334 { 335 p.m_accessList = new AclImpl(); 336 337 for( Enumeration< AclEntry > entries = m_accessList.entries(); entries.hasMoreElements(); ) 338 { 339 AclEntry e = entries.nextElement(); 340 341 p.m_accessList.addEntry( e ); 342 } 343 } 344 345 return p; 346 } 347 348 /** 349 * Compares a page with another using the defined PageNameComparator. See org.apache.wiki.util.PageSorter. 350 * 351 * @param page The object to compare against 352 * @return -1, 0 or 1 353 */ 354 public int compareTo( Object page ) 355 { 356 return m_engine.getPageSorter().compare( this, (WikiPage) page ); 357 } 358 359 /** 360 * A page is equal to another page if its name and version are equal. 361 * 362 * {@inheritDoc} 363 */ 364 // TODO: I have a suspicion that defining this method causes some problems 365 // with page attributes and caching. So as of 2.7.32, it's disabled. 366 /* 367 public boolean equals( Object o ) 368 { 369 if( o != null && o instanceof WikiPage ) 370 { 371 WikiPage oo = (WikiPage) o; 372 373 if( oo.getName().equals( getName() ) ) 374 { 375 if( oo.getVersion() == getVersion() ) 376 { 377 return true; 378 } 379 } 380 } 381 382 return false; 383 } 384 */ 385 /** 386 * {@inheritDoc} 387 */ 388 public int hashCode() 389 { 390 return m_name.hashCode() * m_version; 391 } 392 }