Coverage report

  %line %branch
tsukuba_bunko.peko.session.SessionManager
0% 
0% 

 1  
 /*
 2  
  * All Rights Reserved.
 3  
  * Copyright (C) 1999-2005 Tsukuba Bunko.
 4  
  *
 5  
  * Licensed under the BSD License ("the License"); you may not use
 6  
  * this file except in compliance with the License.
 7  
  * You may obtain a copy of the License at
 8  
  *
 9  
  *       http://www.tsukuba-bunko.org/licenses/LICENSE.txt
 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  
  * $Id: SessionManager.java,v 1.3 2005/09/04 16:10:14 ppoi Exp $
 18  
  */
 19  
 package tsukuba_bunko.peko.session;
 20  
 
 21  
 import java.io.File;
 22  
 import java.io.FileInputStream;
 23  
 import java.io.FileOutputStream;
 24  
 import java.io.ObjectInputStream;
 25  
 import java.io.ObjectOutputStream;
 26  
 import java.net.JarURLConnection;
 27  
 import java.net.URL;
 28  
 import java.net.URLConnection;
 29  
 
 30  
 import java.text.DecimalFormat;
 31  
 
 32  
 import java.util.Date;
 33  
 import java.util.HashSet;
 34  
 
 35  
 import javax.swing.JOptionPane;
 36  
 
 37  
 import tsukuba_bunko.peko.Logger;
 38  
 import tsukuba_bunko.peko.PekoSystem;
 39  
 
 40  
 import tsukuba_bunko.peko.resource.ResourceManager;
 41  
 import tsukuba_bunko.peko.session.MessageIDs;
 42  
 
 43  
 
 44  
 /**
 45  
  * セーブデータの管理を行います。
 46  
  * @author	$Author: ppoi $
 47  
  * @version	$Revision: 1.3 $
 48  
  */
 49  
 public class SessionManager	{
 50  
 
 51  
 	/**
 52  
 	 * セーブデータ ID のフォーマッタ
 53  
 	 */
 54  0
 	protected static final DecimalFormat	FORMAT = new DecimalFormat( "000" );
 55  
 
 56  
 
 57  
 	/**
 58  
 	 * 前回選択したインデックス
 59  
 	 */
 60  0
 	protected int	_lastIndex = -1;
 61  
 
 62  
 	/**
 63  
 	 * システムセーブデータ
 64  
 	 */
 65  0
 	protected SystemSaveData	_systemSaveData = null;
 66  
 
 67  
 	/**
 68  
 	 * 現在のセッション
 69  
 	 */
 70  0
 	protected Session	_session = null;
 71  
 
 72  
 
 73  
 	/**
 74  
 	 * <code>SessionManager</code> のインスタンスを生成します。
 75  
 	 */
 76  
 	public SessionManager()
 77  
 	{
 78  0
 		super();
 79  
 
 80  
 		try	{
 81  0
 			_systemSaveData = loadSystemSaveData();
 82  
 		}
 83  0
 		catch( Exception e )	{
 84  0
 			Logger.debug( "[session.manager] fail to load SystemSaveData.", e );
 85  0
 		}
 86  
 
 87  0
 		_session = new Session();
 88  0
 		_session.setSessionFlagSet( new HashSet(89) );
 89  0
 		if( _systemSaveData != null )	{
 90  0
 			_session.setSystemFlagSet( _systemSaveData.getSystemFlagSet(), _systemSaveData.getSaveDataInfo().getTimestamp() );
 91  0
 		}
 92  
 		else	{
 93  0
 			_systemSaveData = new SystemSaveData();
 94  0
 			SaveDataInfo	info = new SaveDataInfo();
 95  0
 			info.setID( -1 );
 96  0
 			info.setTitle( "PVNS System Save Data" );
 97  0
 			_systemSaveData.setSaveDataInfo( info );
 98  
 
 99  0
 			_session.setSystemFlagSet( new HashSet(89), null );
 100  
 		}
 101  0
 	}
 102  
 
 103  
 
 104  
 	/**
 105  
 	 * 現在のセッションを初期化します。
 106  
 	 */
 107  
 	public void initializeSession()
 108  
 	{
 109  0
 		_session.setSessionFlagSet( new HashSet(89) );
 110  0
 		_session.setSceneContext( null );
 111  0
 	}
 112  
 
 113  
 	/**
 114  
 	 * 現在のセッションを取得します。
 115  
 	 * @return	現在のセッション
 116  
 	 */
 117  
 	public Session getSession()
 118  
 	{
 119  0
 		return _session;
 120  
 	}
 121  
 
 122  
 	/**
 123  
 	 * システムセーブデータを取得します。
 124  
 	 * @return	システムセーブデータ
 125  
 	 */
 126  
 	public SystemSaveData getSystemSaveData()
 127  
 	{
 128  0
 		return _systemSaveData;
 129  
 	}
 130  
 
 131  
 
 132  
 	/**
 133  
 	 * 現在のセッションを保存します。
 134  
 	 */
 135  
 	public void saveCurrentSession()
 136  
 		throws SaveFailureException
 137  
 	{
 138  0
 		SaveData	saveData = new SaveData();
 139  0
 		SaveDataInfo	saveDataInfo = new SaveDataInfo();
 140  0
 		saveDataInfo.setTitle( _session.getSceneContext().getSceneTitle() );
 141  
 
 142  0
 		saveData.setSaveDataInfo( saveDataInfo );
 143  0
 		saveData.setSession( _session );
 144  
 
 145  0
 		save( saveData );
 146  0
 	}
 147  
 
 148  
 
 149  
 	/**
 150  
 	 * セーブデータ一覧を取得します。
 151  
 	 * @param	beginIndex	開始インデックス
 152  
 	 * @param	size	取得サイズ
 153  
 	 * @return	セーブデータ一覧
 154  
 	 */
 155  
 	protected SaveDataInfo[] getSaveDataInfoList( int beginIndex, class="keyword">int size )
 156  
 	{
 157  0
 		SaveDataInfo[]	list = new SaveDataInfo[ size ];
 158  0
 		File	saveFile = null;
 159  0
 		SaveData	saveData = null;
 160  0
 		SaveDataInfo	saveDataInfo = null;
 161  0
 		Object	data = null;
 162  0
 		FileInputStream	fis = null;
 163  0
 		ObjectInputStream	ois = null;
 164  0
 		for( int i = 0; i < list.length; ++i )	{
 165  0
 			saveFile = getSaveFile( i + beginIndex );
 166  0
 			if( saveFile.isFile() )	{
 167  
 				try	{
 168  0
 					fis = new FileInputStream( saveFile );
 169  0
 					ois = new ObjectInputStream( fis );
 170  0
 					data = ois.readObject();
 171  
 				}
 172  0
 				catch( Exception e )	{
 173  0
 					Logger.warn( MessageIDs.SAV0008W, new Object[]{String.valueOf(i + beginIndex)}, e );
 174  
 				}
 175  
 				finally	{
 176  0
 					if( ois != null )	{
 177  
 						try	{
 178  0
 							ois.close();
 179  
 						}
 180  0
 						catch( Exception e )	{
 181  0
 							Logger.warn( MessageIDs.SAV0004W, e );
 182  0
 						}
 183  0
 					}
 184  0
 					else if( fis != null )	{
 185  
 						try	{
 186  0
 							fis.close();
 187  
 						}
 188  0
 						catch( Exception e )	{
 189  0
 							Logger.warn( MessageIDs.SAV0004W, e );
 190  0
 						}
 191  
 					}
 192  0
 					ois = null;
 193  0
 					fis = null;
 194  0
 				}
 195  
 
 196  0
 				if( data instanceof SaveData )	{
 197  0
 					saveData = (SaveData)data;
 198  0
 					if( saveData != null )	{
 199  0
 						saveDataInfo = saveData.getSaveDataInfo();
 200  0
 						if( (saveDataInfo != null) && (saveDataInfo.getTitle() != class="keyword">null) && (saveDataInfo.getTimestamp() != class="keyword">null) )	{
 201  0
 							list[i] = saveDataInfo;
 202  0
 						}
 203  
 					}
 204  
 					else	{
 205  0
 						Logger.warn( MessageIDs.SAV0022W, new Object[]{String.valueOf(i)} );
 206  
 					}
 207  
 				}
 208  
 			}
 209  
 		}
 210  
 
 211  0
 		return list;
 212  
 	}
 213  
 
 214  
 	/**
 215  
 	 * セーブデータを保存します。
 216  
 	 * @param	data	保存するセーブデータ
 217  
 	 * @throws	SaveFailureException
 218  
 	 */
 219  
 	protected void save( SaveData data )
 220  
 		throws SaveFailureException
 221  
 	{
 222  0
 		SaveDataInfo[]	list = getSaveDataInfoList( 0, 20 );
 223  0
 		int	index = SaveDataDialog.showDialog( list, getInitialSelectedIndexForSave(list), true );
 224  0
 		Logger.debug( "index: " + index );
 225  0
 		if( index == -1 )	{
 226  0
 			return;
 227  
 		}
 228  
 		else	{
 229  0
 			data.getSaveDataInfo().setID( index );
 230  
 		}
 231  0
 		Date	timestamp = new Date();
 232  0
 		data.getSaveDataInfo().setTimestamp( timestamp );
 233  
 
 234  0
 		FileOutputStream	fos = null;
 235  0
 		ObjectOutputStream	oos = null;
 236  
 		try	{
 237  0
 			File	path = getSaveFile( data.getSaveDataInfo().getID() );
 238  0
 			Logger.debug( "save to " + path.getAbsolutePath() );
 239  
 
 240  0
 			fos = new FileOutputStream( path );
 241  
 
 242  0
 			oos = new ObjectOutputStream( fos );
 243  0
 			oos.writeObject( data );
 244  0
 			oos.flush();
 245  0
 			_lastIndex = index;
 246  
 		}
 247  0
 		catch( Exception e )	{
 248  0
 			Logger.error( MessageIDs.SAV0001E, new Object[]{String.valueOf(data.getSaveDataInfo().getID())}, e );
 249  0
 			SaveFailureException	sfe = new SaveFailureException( "fail to save.", e );
 250  0
 			throw sfe;
 251  
 		}
 252  
 		finally	{
 253  0
 			if( oos != null )	{
 254  
 				try	{
 255  0
 					oos.close();
 256  
 				}
 257  0
 				catch( Exception e )	{
 258  0
 					Logger.warn( MessageIDs.SAV0002W, e );
 259  0
 				}
 260  0
 			}
 261  0
 			else if( fos != null )	{
 262  
 				try	{
 263  0
 					fos.close();
 264  
 				}
 265  0
 				catch( Exception e )	{
 266  0
 					Logger.warn( MessageIDs.SAV0002W, e );
 267  0
 				}
 268  0
 			}
 269  0
 		}
 270  0
 	}
 271  
 
 272  
 
 273  
 
 274  
 	/**
 275  
 	 * セーブデータを読み込みます。
 276  
 	 * @return	セーブデータをロードした場合 <code>true</code>,ロードしなかった場合 <code>false</code>。
 277  
 	 * @throws	LoadFailureException	ロードに失敗した場合
 278  
 	 */
 279  
 	public boolean load()
 280  
 		throws LoadFailureException
 281  
 	{
 282  0
 		SaveDataInfo[]	list = getSaveDataInfoList( 0, 20 );
 283  0
 		boolean	nodata = false;
 284  0
 		if( list != null )	{
 285  0
 			nodata = true;
 286  0
 			for( int i = 0; i < list.length; ++i )	{
 287  0
 				if( list[i] != null )	{
 288  0
 					nodata = false;
 289  
 				}
 290  
 			}
 291  0
 		}
 292  
 		else	{
 293  0
 			nodata = true;
 294  
 		}
 295  
 
 296  0
 		if( nodata )	{
 297  0
 			ResourceManager	resources = ResourceManager.getInstance();
 298  0
 			String	title = (String)resources.getResource( ResourceIDs.DIALOG_NOTIFY_NODATA_TITLE );
 299  0
 			if( title == null )	{
 300  0
 				Logger.warn( MessageIDs.SAV0020W );
 301  
 			}
 302  0
 			String	message = (String)resources.getResource( ResourceIDs.DIALOG_NOTIFY_NODATA_MESSAGE );
 303  0
 			if( message == null )	{
 304  0
 				message = "No save data for loading.";
 305  0
 				Logger.warn( MessageIDs.SAV0021W, new Object[]{"\"" + message + "\""} );
 306  
 			}
 307  0
 			JOptionPane.showMessageDialog( PekoSystem.getInstance().getMainWindow(), message, title, JOptionPane.INFORMATION_MESSAGE );
 308  0
 			return false;
 309  
 		}
 310  
 
 311  0
 		int	index = SaveDataDialog.showDialog( list, getInitialSelectedIndexForLoad(list), false );
 312  0
 		if( index == -1 )	{
 313  0
 			return false;
 314  
 		}
 315  
 
 316  0
 		File	path = getSaveFile( index );
 317  0
 		if( !path.exists() )	{
 318  0
 			Logger.error( MessageIDs.SAV0005E, new Object[]{String.valueOf(index)} );
 319  0
 			LoadFailureException	lfe = new LoadFailureException( "no such save file" );
 320  0
 			throw lfe;
 321  
 		}
 322  
 
 323  0
 		FileInputStream	fis = null;
 324  0
 		ObjectInputStream	ois = null;
 325  
 		try	{
 326  0
 			fis = new FileInputStream( path );
 327  0
 			ois = new ObjectInputStream( fis );
 328  
 
 329  0
 			SaveData	data = (SaveData)ois.readObject();
 330  0
 			if( !isValidData(data) )	{
 331  0
 				Logger.error( MessageIDs.SAV0025E );
 332  0
 				return false;
 333  
 			}
 334  
 
 335  0
 			Session	session = data.getSession();
 336  0
 			session.setSystemFlagSet( _session.getSystemFlagSet(), _session.getTimestamp() );
 337  0
 			_session = session;
 338  
 
 339  0
 			_lastIndex = index;
 340  0
 			return true;
 341  
 		}
 342  0
 		catch( Exception e )	{
 343  0
 			Logger.error( MessageIDs.SAV0003E, new Object[]{String.valueOf(String.valueOf(index))}, e );
 344  0
 			LoadFailureException	lfe = new LoadFailureException( "fail to load.", e );
 345  0
 			throw lfe;
 346  
 		}
 347  
 		finally	{
 348  0
 			if( ois != null )	{
 349  
 				try	{
 350  0
 					ois.close();
 351  
 				}
 352  0
 				catch( Exception e )	{
 353  0
 					Logger.warn( MessageIDs.SAV0004W, e );
 354  0
 				}
 355  0
 			}
 356  0
 			else if( fis != null )	{
 357  
 				try	{
 358  0
 					fis.close();
 359  
 				}
 360  0
 				catch( Exception e )	{
 361  0
 					Logger.warn( MessageIDs.SAV0004W, e );
 362  0
 				}
 363  
 			}
 364  0
 		}
 365  
 	}
 366  
 
 367  
 	/**
 368  
 	 * システムセーブデータを保存します。
 369  
 	 */
 370  
 	public void saveSystemSaveData()
 371  
 		throws SaveFailureException
 372  
 	{
 373  0
 		Logger.debug( "save SystemSaveData." );
 374  0
 		SystemSaveData	data = _systemSaveData;
 375  0
 		data.setSystemFlagSet( _session.getSystemFlagSet() );
 376  0
 		FileOutputStream	fos = null;
 377  0
 		ObjectOutputStream	oos = null;
 378  
 		try	{
 379  0
 			data.getSaveDataInfo().setTimestamp( new Date() );
 380  
 
 381  0
 			File	path = getSystemSaveFile();
 382  
 
 383  0
 			fos = new FileOutputStream( path );
 384  
 
 385  0
 			oos = new ObjectOutputStream( fos );
 386  0
 			oos.writeObject( data );
 387  0
 			oos.flush();
 388  
 		}
 389  0
 		catch( Exception e )	{
 390  0
 			Logger.error( MessageIDs.SAV0006F, e );
 391  0
 			SaveFailureException	sfe = new SaveFailureException( "fail to save system save data.", e );
 392  0
 			throw sfe;
 393  
 		}
 394  
 		finally	{
 395  0
 			if( oos != null )	{
 396  
 				try	{
 397  0
 					oos.close();
 398  
 				}
 399  0
 				catch( Exception e )	{
 400  0
 					Logger.warn( MessageIDs.SAV0002W, e );
 401  0
 				}
 402  0
 			}
 403  0
 			else if( fos != null )	{
 404  
 				try	{
 405  0
 					fos.close();
 406  
 				}
 407  0
 				catch( Exception e )	{
 408  0
 					Logger.warn( MessageIDs.SAV0002W, e );
 409  0
 				}
 410  0
 			}
 411  0
 		}
 412  0
 	}
 413  
 
 414  
 	/**
 415  
 	 * システムセーブデータを読み込みます。
 416  
 	 * @return	システムセーブデータ
 417  
 	 * @throws	LoadFailureException	読み込みに失敗した場合
 418  
 	 */
 419  
 	public SystemSaveData loadSystemSaveData()
 420  
 		throws LoadFailureException
 421  
 	{
 422  0
 		SystemSaveData	saveData = null;
 423  
 
 424  0
 		File	path = getSystemSaveFile();
 425  0
 		if( !path.exists() )	{
 426  0
 			return null;
 427  
 		}
 428  
 
 429  0
 		FileInputStream	fis = null;
 430  0
 		ObjectInputStream	ois = null;
 431  
 		try	{
 432  0
 			fis = new FileInputStream( path );
 433  0
 			ois = new ObjectInputStream( fis );
 434  
 
 435  0
 			saveData = (SystemSaveData)ois.readObject();
 436  
 		}
 437  0
 		catch( Exception e )	{
 438  0
 			Logger.fatal( MessageIDs.SAV0006F, e );
 439  0
 			LoadFailureException	lfe = new LoadFailureException( "fail to load.", e );
 440  0
 			throw lfe;
 441  
 		}
 442  
 		finally	{
 443  0
 			if( ois != null )	{
 444  
 				try	{
 445  0
 					ois.close();
 446  
 				}
 447  0
 				catch( Exception e )	{
 448  0
 					Logger.warn( MessageIDs.SAV0004W, e );
 449  0
 				}
 450  0
 			}
 451  0
 			else if( fis != null )	{
 452  
 				try	{
 453  0
 					fis.close();
 454  
 				}
 455  0
 				catch( Exception e )	{
 456  0
 					Logger.warn( MessageIDs.SAV0004W, e );
 457  0
 				}
 458  0
 			}
 459  0
 		}
 460  
 
 461  0
 		return saveData;
 462  
 	}
 463  
 
 464  
 	/**
 465  
 	 * <code>id</code> で識別されるセーブデータを格納するセーブファイルを取得します。
 466  
 	 * @param	id	セーブデータ ID
 467  
 	 * @return	セーブファイル
 468  
 	 */
 469  
 	protected File getSaveFile( int id )
 470  
 	{
 471  0
 		ResourceManager	resources = ResourceManager.getInstance();
 472  0
 		return new File( resources.getLocationResources().getSaveDirectory(), "save" + FORMAT.format(new Integer(id)) + ".dat" );
 473  
 	}
 474  
 
 475  
 	/**
 476  
 	 * システムの状態を保存するセーブデータを格納するセーブファイルを取得します。
 477  
 	 * @return	セーブファイル
 478  
 	 */
 479  
 	protected File getSystemSaveFile()
 480  
 	{
 481  0
 		ResourceManager	resources = ResourceManager.getInstance();
 482  0
 		return new File( resources.getLocationResources().getSaveDirectory(), "config.dat" );
 483  
 	}
 484  
 
 485  
 	/**
 486  
 	 * セーブ時に最初に選択されているインデックスを取得します。
 487  
 	 * @param	list	一覧
 488  
 	 * @return	セーブ時に最初に選択されているインデックス
 489  
 	 */
 490  
 	protected int getInitialSelectedIndexForSave( SaveDataInfo[] list )
 491  
 	{
 492  0
 		if( (list == null) || (list.length == 0) )	{
 493  0
 			throw new IllegalArgumentException( "void list is specified." );
 494  
 		}
 495  
 
 496  0
 		int	selected = 0;
 497  0
 		SaveDataInfo	info = null;
 498  0
 		for( int i = 0; i < list.length; ++i )	{
 499  0
 			info = list[i];
 500  0
 			if( info == null )	{
 501  0
 				selected = i;
 502  0
 				break;
 503  
 			}
 504  
 			else	{
 505  0
 				if( (list[selected] == null) || info.getTimestamp().before(list[selected].getTimestamp()) )	{
 506  0
 					selected = i;
 507  
 				}
 508  
 			}
 509  
 		}
 510  0
 		return selected;
 511  
 	}
 512  
 
 513  
 	/**
 514  
 	 * ロード時に最初に選択されているインデックスを取得します。
 515  
 	 * @param	list	一覧
 516  
 	 * @return	ロード時に最初に選択されているインデックス
 517  
 	 */
 518  
 	protected int getInitialSelectedIndexForLoad( SaveDataInfo[] list )
 519  
 	{
 520  0
 		if( (list == null) || (list.length == 0) )	{
 521  0
 			throw new IllegalArgumentException( "void list is specified." );
 522  
 		}
 523  
 
 524  0
 		if( _lastIndex != -1 )	{
 525  0
 			return _lastIndex;
 526  
 		}
 527  
 
 528  0
 		int	selected = 0;
 529  0
 		SaveDataInfo	info = null;
 530  0
 		for( int i = 0; i < list.length; ++i )	{
 531  0
 			info = list[i];
 532  0
 			if( info != null )	{
 533  0
 				if( (list[selected] == null) || info.getTimestamp().after(list[selected].getTimestamp()) )	{
 534  0
 					selected = i;
 535  
 				}
 536  
 			}
 537  
 		}
 538  0
 		return selected;
 539  
 	}
 540  
 
 541  
 	/**
 542  
 	 * セーブデータの妥当性検証をします。
 543  
 	 * @param	data	セーブデータ
 544  
 	 * @return	妥当な場合 <code>true</code>,使用不能な場合 <code>false</code>
 545  
 	 */
 546  
 	protected boolean isValidData( SaveData data )
 547  
 	{
 548  0
 		String	sceneName = data.getSession().getSceneContext().getSceneName();
 549  0
 		URL	sceneURL = getSceneURL( sceneName );
 550  0
 		long	lastModified = 0L;
 551  
 		try	{
 552  0
 			URLConnection	connection = sceneURL.openConnection();
 553  0
 			connection.connect();
 554  0
 			if( connection instanceof JarURLConnection )	{
 555  0
 				JarURLConnection	jarconnection = (JarURLConnection)connection;
 556  0
 				lastModified = jarconnection.getJarEntry().getTime();
 557  0
 			}
 558  
 			else	{
 559  0
 				lastModified = connection.getLastModified();
 560  
 			}
 561  0
 			Logger.info( "last modified time=" + new java.util.Date(lastModified) + ", scene=" + sceneName );
 562  
 		}
 563  0
 		catch( Exception ex )	{
 564  0
 			Logger.warn( "fail to get last modified timestamp.", ex );
 565  0
 		}
 566  
 
 567  0
 		if( lastModclass="keyword">ified > 0L )	{
 568  0
 			return (data.getSaveDataInfo().getTimestamp().getTime() >= lastModified);
 569  
 		}
 570  
 		else	{
 571  0
 			return true;
 572  
 		}
 573  
 	}
 574  
 
 575  
 	/**
 576  
 	 * シーンデータの URL を取得します。
 577  
 	 * @param	scene	シーン名
 578  
 	 * @return	シーンデータの URL
 579  
 	 */
 580  
 	protected URL getSceneURL( String scene )
 581  
 	{
 582  0
 		ResourceManager	resources = ResourceManager.getInstance();
 583  0
 		URL	sceneDir = resources.getLocationResources().getScenesDirecotryURL();
 584  
 		try	{
 585  0
 			return new URL( sceneDir, scene );
 586  
 		}
 587  0
 		catch( Exception e )	{
 588  0
 			Logger.fatal( tsukuba_bunko.peko.scenario.MessageIDs.SCN0006F, e );
 589  0
 			PekoSystem.showErrorDialog( tsukuba_bunko.peko.scenario.MessageIDs.SCN0006F.getMessage(), e, true );
 590  0
 			return null;
 591  
 		}
 592  
 	}
 593  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.